Виклик функції 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;
}
}