Вызываемая функция hook_menu()
- menu_router_build () , вызываемая menu_rebuild () . Он содержит следующий код.
foreach (module_implements('menu') as $module) {
$router_items = call_user_func($module . '_menu');
if (isset($router_items) && is_array($router_items)) {
foreach (array_keys($router_items) as $path) {
$router_items[$path]['module'] = $module;
}
$callbacks = array_merge($callbacks, $router_items);
}
}
// Alter the menu as defined in modules, keys are like user/%user.
drupal_alter('menu', $callbacks);
Если есть два модуля, определяющих один и тот же маршрут, последний модуль в массиве, возвращенном module_implements()
функцией, переопределит значение, определенное для других модулей.
Второй требуемый параметр module_implements()
определяется как:
$sort
По умолчанию модули упорядочены по весу и имени файла, при настройке этой опции TRUE
список модулей будет упорядочен по имени модуля.
Поскольку menu_router_build()
второй параметр не передается menu_implements()
, функция использует значение по умолчанию для этого параметра. Это означает, что список модулей упорядочен по их весу и имени файла; когда два модуля имеют одинаковый вес, первый модуль, который появляется в списке, является первым в алфавитном порядке.
Кроме того, любой реализующий модуль hook_module_implements_alter()
может изменить порядок вызова хуков.
По этой причине вы не должны предполагать, что знаете, в каком порядке вызываются хуки.
Если целью кода является изменение маршрута, реализованного другим модулем, например, потому что маршрут должен быть удален при установке и включении второго модуля, следует использовать код hook_menu_alter()
. Если вы пытаетесь понять, какой модуль «победит» в случае конфликтов маршрутов, я бы предпочел избежать такого конфликта маршрутов и определить маршрут, который еще не определен из другого модуля.
Если затем вы реализуете hook_menu_alter()
и хотите быть уверенным, что ваш модуль выполняется последним, чтобы быть модулем, который эффективно переопределяет маршрут, вы должны также реализовать его hook_module_implements_alter()
.
function mymodule_module_implements_alter(&$implementations, $hook) {
if ($hook == 'menu_alter') {
// Move mymodule_menu_alter() to the end of the list. module_implements()
// iterates through $implementations with a foreach loop which PHP iterates
// in the order that the items were added, so to move an item to the end of
// the array, we remove it and then add it.
$group = $implementations['mymodule'];
unset($implementations['mymodule']);
$implementations['mymodule'] = $group;
}
}
hook_menu_alter()
используется не для определения новых меню, а для изменения существующих. Если два модуля изменяют одно и то же меню, то изменение, которое сохраняется, является тем из модуля, который выполняется последним.Какой из модулей имеет меньшее
weight
значение вsystem
таблице, будет вызван первым, поэтомуweight
в этом случае модуль с более высоким значением будет «выигрывать».Если весовые коэффициенты одинаковы для двух (или более) модулей, я полагаю, что никакого конкретного упорядочения не производится, кроме упорядочения, получаемого непосредственно из таблицы MySQL (хотя я могу ошибаться в этом).
Поскольку возвращаемые результаты вызова
hook_menu
просто помещаются в один массив пунктов меню, «конфликт» как таковой никогда не возникнет, результаты последующих вызововhook_menu
просто переопределят результаты предыдущих вызовов.источник
module_implements()
получит вFALSE
качестве второго параметра, но функции, такие какmodule_invoke_all()
вызовы, только с параметром.