Элементы, отображаемые в меню, не могут быть созданы с помощью элемента с маршрутизатором с подстановочными знаками: каждый элемент меню соответствует ровно одному пути.То есть, если у вас есть элемент маршрутизатора foo/%bar
и %bar
может иметь 10 различных значений, система меню Drupal не собирается создавать 10 новых пунктов меню из одного определения элемента маршрутизатора.
Поэтому вам нужно заранее создать элемент маршрутизатора для каждого возможного аргумента.В противном случае вам придется заглянуть за пределы системы меню Drupal и подумать о создании отдельного блока Views, который выглядит как меню, но на самом деле представляет собой неупорядоченный список Views с доступными опциями.
Чтобы сделать первое,вам нужно реализовать hook_menu_alter()
, чтобы добавить свой настраиваемый элемент маршрутизатора после всего остального, включая шаблонный символ маршрутизатора, который вы пытаетесь переопределить.Ваш пользовательский элемент маршрутизатора будет более или менее таким же, как элемент маршрутизатора с подстановочными символами, но с некоторыми настройками по умолчанию, которые обычно будут получены из подстановочного знака.
Например, если бы я хотел создать новый элемент маршрутизатора дляuser/1/edit
, который переопределяет встроенный user/%user_category/edit
, я бы реализовал hook_menu_alter()
следующим образом:
function mymodule_menu_alter(&$items) {
// user_edit and user_edit_access expect a user object
$account = user_load(array('uid' => 1));
$items['user/1/edit'] = array(
'type' => MENU_CALLBACK,
'page arguments' => array($account),
'access arguments' => array($account),
) + $items['user/%user_category/edit'];
}
В этом примере user/%user_category/edit
вызывает user_edit()
иuser_edit_access()
для страницы и обратных вызовов доступа соответственно, и они оба пытаются использовать подстановочный знак.Поскольку в элементе маршрутизатора нет подстановочного знака, необходимо переопределить аргументы, чтобы сказать «проверьте пользователя 1».
Вы будете делать это для каждого возможного значения подстановочного знака.
Но этого недостаточно: обратите внимание, я использовал MENU_CALLBACK
вместо MENU_NORMAL_ITEM
.Если вы используете MENU_NORMAL_ITEM
, ваш маршрутизатор будет отображаться в меню Navigation , а не в вашем пользовательском меню, даже если вы установили menu_name
(я не знаю, почему это так: должно работать).Но вы можете обойти это, используя menu_link_save()
.
Рассмотрите эту реализацию hook_init()
:
function mymodule_init() {
$router_path = 'user/1/edit';
// Check to see if the custom router item has been added to menu_links.
// This is to ensure the menu has already been rebuilt.
$router_item = db_fetch_object(db_query("SELECT * FROM {menu_links} WHERE router_path = '%s'", $router_path));
// Only create a new menu item if the router item exists and it
// hasn't already been created (it's hidden until created).
if ($router_item && $router_item->hidden) {
$item = array(
'link_title' => 'Edit Administrator',
'link_path' => $router_path,
'menu_name' => 'primary-links',
'router_path' => $router_path,
'mlid' => $router_item->mlid,
);
// Save the menu item.
menu_link_save($item);
}
}
В этой реализации, он проверяет, был ли пользовательский маршрутизатор уже создан и не был ли изменен в противном случае.Если это так, то в главном меню ссылок создается ссылка меню, которая ссылается на ваш пользовательский элемент маршрутизатора.
Очевидно, поскольку это hook_init()
, проверка будет выполняться на каждой странице:чтобы оно срабатывало после перестроения меню.Это не должно сильно сказываться на производительности, но об этом нужно помнить.
Как видите, это долгий и затяжной процесс: если вы не собираетесь идтиПросматривает фальшивое меню маршрута, может быть лучше просто вручную создать ссылки.