Wywoływanie funkcji hook_menu()
to menu_router_build () , wywoływane przez menu_rebuild () . Zawiera następujący kod.
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);
Jeśli istnieją dwa moduły definiujące tę samą trasę, ostatni moduł w tablicy zwróconej przez module_implements()
zastąpi wartość zdefiniowaną w innych modułach.
Drugi wymagany parametr module_implements()
jest zdefiniowany jako:
$sort
Domyślnie moduły są uporządkowane według wagi i nazwy pliku, ustaw tę opcję na TRUE
, lista modułów zostanie uporządkowana według nazwy modułu.
Ponieważ menu_router_build()
nie przekazuje drugiego parametru do menu_implements()
, funkcja korzysta z domyślnej wartości tego parametru. Oznacza to, że lista modułów jest uporządkowana według wagi i nazwy pliku; gdy dwa moduły mają taką samą wagę, pierwszym modułem, który pojawia się na liście, jest ten, który jest alfabetycznie pierwszy.
Ponadto, każdy moduł implementujący hook_module_implements_alter()
może zmienić kolejność wywoływania haków.
Z tego powodu nie powinieneś zakładać, że wiesz, w jakiej kolejności są wywoływane haki.
Jeśli celem kodu jest zmiana trasy zaimplementowanej przez inny moduł, na przykład ponieważ trasa powinna zostać usunięta po zainstalowaniu i włączeniu drugiego modułu, kod powinien użyć hook_menu_alter()
. Jeśli próbujesz zrozumieć, który moduł „wygrałby” w przypadku konfliktu trasy, wolałbym uniknąć takiego konfliktu trasy i zdefiniować trasę, która nie jest jeszcze zdefiniowana w innym module.
Jeśli następnie wdrażasz hook_menu_alter()
i chcesz mieć pewność, że moduł jest wykonywany jako ostatni, aby być modułem, który skutecznie zastępuje trasę, powinieneś hook_module_implements_alter()
również wdrożyć .
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()
nie służy do definiowania nowych menu, ale do zmiany istniejących. Jeśli dwa moduły zmienią to samo menu, zachowana zostanie zmiana z modułu wykonanego na końcu.Ten, który moduł ma niższą
weight
wartość wsystem
tabeli, zostanie wywołany jako pierwszy, więc moduł o wyższejweight
wartości „wygra” w tym przypadku.Jeśli wagi są takie same dla dwóch (lub więcej) modułów, uważam, że nie jest wykonywane żadne konkretne zamówienie poza zamówieniem, które pochodzi bezpośrednio z tabeli MySQL (choć mogę się mylić).
Ponieważ wyniki zwracane z wywołania
hook_menu
są po prostu umieszczane w jednej tablicy pozycji menu, nigdy nie będzie „konfliktu” jako takiego, wyniki późniejszych wywołańhook_menu
po prostu zastąpią te z wcześniejszych wywołań.źródło
module_implements()
otrzymałFALSE
jako drugi parametr, ale działa jakmodule_invoke_all()
wywołuje go tylko z parametrem.