Быстрая CMS
Обратная связь Карта сайта
Главная Создание сайтов Практика Строим CMS Наивное О проекте Блог

Формирование меню

HTML-код меню обычно регулярный – то есть, состоит из повторяющихся последовательностей «начало блока – ссылка – конец блока». Обрамляющим ссылку блоком могут быть разные элементы, это зависит от дизайна страницы. Для простоты предположим, что главное меню у нас горизонтальное, под шапкой страницы, а меню раздела вертикальное, расположено в боковой колонке. В этом случае разделителем пунктов главного меню будет просто пробельный символ, а для меню раздела – перевод строки.

Не забываем, что вид ссылок в меню будет зависеть от режима ЧПУ (режим у нас задает переменная $urlmode в файле конфигурации). В каждом режиме формирование ссылок будет идти по-разному. Чтобы не плодить массу условных операторов, проще всего сделать по библиотечке формирования меню для каждого режима. А при выполнении центрального скрипта подгружать нужную библиотеку в зависимости от режима. Так и поступим. Файлы библиотек назовем так, чтобы в имени файла содержалось название режима – это нам позволит очень просто определить, какую библиотеку загружать.

Для начала сделаем формирование меню в режиме реальных ссылок, а преобразованием URL займемся позже. В директории /libs размещаем файл m_none.inc.php, содержащий функцию:


<?php
function getmenu($var) {
global $_pageid;
 $menu=array();
 foreach ($var as $key=>$val) {
  if (((int)$val['some'] & 1) == 0) {
   if (((int)$val['some'] & 16) > 0) $href='"'.$val['knot'].'"';
   else
   $href=($val['knot']!='/' ? '"main.php?'.$_pageid.'='.$val['knot'].'"':'"/"');
   $menu[]='<a href='.$href.'>'.$val['name'].'</a>';
  }
 }
  return ($menu);
}
?>

Функция получает параметром ($var) массив выбранных для меню разделов и перебирает его в цикле, формируя строку ссылки для каждого раздела. В итоге она возвращает массив сформированных ссылок на разделы. Глобальная переменная $_pageid содержит название GET-параметра – идентификатора раздела. В файле конфигурации прописано значение 'id'.

Две первые строки в цикле foreach проверяют битовую маску статуса раздела. Взведенный 0-й разряд (значение 1) требует не включать раздел в меню. 4-й разряд (значение 16) означает скрипт стороннего разработчика, ссылка на который должна включаться в меню без изменений, как она есть. В этом случае алиасом раздела должна быть ссылка на скрипт вместе с маршрутом от корневой директории сайта (например, /forum/index.php).

В дальнейшем для формирования меню в других режимах нам потребуется написать аналогичные функции с тем же названием для статических ссылок двух видов и поместить их в файлы m_static.inc.php и m_subdir.inc.php. Тогда по наименованию режима из файла конфигурации скрипт может сформировать имя файла, из которого подгрузит нужный вариант функции.

Далее при разработке плагинов (карты сайта и многостраничных списков) нам потребуются дополнительные функции формирования ссылок. Их мы можем точно так же написать в трех вариантах для разных видов URL и поместить в те же библиотечные файлы. Таким образом мы получаем три библиотечки работы со ссылками, содержащие одни и те же функции для разных режимов работы движка.

 

Дополнение:

На днях получил письмо с давно ожидаемым вопросом: как сделать все это для структуры сайта с тремя уровнями вложенности? В этом случае возникают сложности с навигацией, которые все внимательные читатели уже заметили на этом сайте. В разделе второго уровня, если у него есть подразделы-«потомки», приходится в качестве внутреннего меню показывать список этих потомков, а меню второго уровня уже нет, и это лишает навигацию удобства и наглядности.

Признаюсь честно: не стал возиться и сделал все максимально просто (собственно, и задачей себе ставил показать максимально простую конструкцию). Можно с помощью ранее описанных функций для фильтрации getlevel() и getsub() отфильтровать подразделы с тем же предком («братьев» текущего раздела) и подразделы третьего уровня – «потомков» текущего. А потом сформировать меню раздела как вложенный ненумерованный список – аналогично описанной далее карте сайта.

При этом можно не полениться и использовать описанный в статье «Структура данных, часть II» идентификатор ветви. Очень просто построить функцию фильтрации, которая будет выбирать только одну ветвь иерархии – раздел верхнего уровня, его потомков и потомков его потомков – по этому идентификатору. Потом из массива данных по ветви все теми же getlevel() и getsub() выбрать смежные и вложенные разделы для данного. При большом числе разделов на сайте такой подход позволит неплохо сократить затраты ресурсов на фильтрацию.

Но это уже домашнее задание для тех, кто разобрался в работе описанного движка и хочет идти дальше... или глубже, как посмотреть. :-) Этих людей ждет еще одно испытание: при построении карты сайта с глубиной вложения разделов больше двух очень трудно обойтись без рекурсивного обхода дерева разделов. На этом сайте карту строит именно рекурсивная функция, она же давно используется в позднейших двухуровневых версиях движка (три уровня нужны редко). Но можно обойтись и без рекурсии, последовательно выбирая ветви. Не буду говорить о том, лучше это или хуже – скажу только, что нет задачи, которую два разных программиста решили бы совершенно одинаково.