Недавно пришлось писать меню для CMS (именно для той о которой я писал в пред идущем посте Хитрости PHP: Якорная вставка функций я еще много про эту CMS расскажу). Думаю многие сталкивались с такой задачей, это не сложный скрипт. Я решил сделать меню, максимально универсально.
Основные требования которые я перед собой поставил при написание меню:
- Возможность быстро и удобно менять внешний вид меню (вертикальное, горизонтальное, выпадающее и тп.), с минимальным присутствием программиста.
- Возможность выводить в меню, пункты модулей (например модуль “новости”, рубрики новостей должны быть подразделами, хотя сами рубрики хранятся отдельно).
Первый пункт я решил, разделив создание меню на две функции, обе рекурсивный. Первая создает многомерный массив вида:
1 2 3 4 5 6 7 8 9 | $menu[]=array( 'id'=>$m['id'], // идентификатор страницы 'pid'=>$m['pid'], // идентификатор родительной страницы 'name'=>$m['name'], // название страницы 'chpu'=>$chpu.'/'.$m['name_ufl'], //адрес страницы 'lavel'=>$lavel, // номер папки в ЧПУ которой соответствует пункт в меню 'select'=>($module[$lavel-1]==$m['name_ufl'] ? 'yes' : 'no'), // идентификатор находится ли пользователь в это разделе/подразделе 'sub'=>(empty($fun) ? menu_array($m['id'],$lavel+1,$chpu.'/'.$m['name_ufl']) : $fun(0,$lavel+1,$chpu.'/'.$m['name_ufl'])) // здесь находится такой же массив с подразделами, эту конструкцию опишу подробнее ); |
А вторая внедряет этот массив в шаблон. Таким образом первый пункт решен, пишем несколько вариантов второй функции и остается только выбрать какой вариант меню нужен, и включить соответствующую функцию.
Со вторым пунктом было сложнее так как вариантов решений было много. Точнее сам алгоритм подходил один, для решения этой задачи - при вызове очередной рекурсии если страница является модулем, вызвать не саму функцию, а функцию модуля, которая создаст массив подразделов. Очень удобное решение, можно создавать подразделы как из базы данных, так и просто выводить статичный массив с подразделами. Но в этом случае есть одно - “НО”. Как мы узнаем как программист назвал функцию создающую массив подразделов этого модуля? Можно сказать, что именно из-за этого вопроса и писалась эта статья.
И так, что мы имеем - путь к папке модуля и необходимость получения инфомации. Изменение, добавление и удаления информации средствами ПО нам не нужно, по этому запихивать название функции в настройки модуля в MySql я категорически не хотел (если все такие мелочи хранить в БД получится большая таблица с частыми запросам к ней, нам это не надо).
Решил я эту задачу так - ввел стандарт в CMS если модуль вставляет что-либо в меню, то нужно создать в папке с модулем файл menu.php который возвращает название функции пример:
<php return "menu_news"; ?>
А перед добавлением элемента в массив идет проверка, является ли страница массивом, включена ли поддержка подразделов модулей и существует ли файл menu.php. Если все верно в переменную $fun инклудится название функции для создания подразделов этого модуля, проверяется на то, что такая функция объявлена, если нет то переменной $fun присваивается пустая строка.
$fun=''; if(!empty($m['module']) and $setting_menu['include_module']=='yes' and file_exists("./modules/".$m['module']."/menu.php")) { $fun=include("./modules/".$m['module']."/menu.php"); if(!function_exists($fun)) $fun=''; }
Дальше идет код по созданию массива, в элемент с ключом ’sub’ добавляется результат следующей рекурсии или функции модуля в зависимости от того пуста переменная $fun или нет.
8 | 'sub'=>(empty($fun) ? menu_array($m['id'],$lavel+1,$chpu.'/'.$m['name_ufl']) : $fun(0,$lavel+1,$chpu.'/'.$m['name_ufl'])) |
В заключение могу сказать, описанный метод хорош только если данные не нужно изменять, а всего лишь приравнять к неопределенной переменной….
P.S. В следующем посте я расскажу как меня пытались кинуть, и что нужно делать в таких случаях.


ну, некоторые детали можно было бы и поподробнее описать
Что именно вам не понятно? Могу объяснить.
если возможно, покажите готовый пример, или скрин с меню, времени мало изучать и проверять то ли это что надо или нет.
Заранее спасибо!
Какой скрин я могу предоставить, если этот скрипт всего лишь позволяет создать массив с пунктами меню. После этого можно создать любое меню, применив нужное оформление.