La funzione che invoca hook_menu()
è menu_router_build () , chiamata da menu_rebuild () . Contiene il seguente codice.
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);
Se esistono due moduli che definiscono la stessa route, l'ultimo modulo dell'array restituito module_implements()
sovrascriverà il valore definito dagli altri moduli.
Il secondo parametro richiesto da module_implements()
è definito come:
$sort
Per impostazione predefinita, i moduli sono ordinati in base al peso e al nome file, le impostazioni su questa opzione TRUE
, l'elenco dei moduli saranno ordinati in base al nome del modulo.
Poiché menu_router_build()
non passa il secondo parametro a menu_implements()
, la funzione utilizza il valore predefinito per quel parametro. Ciò significa che l'elenco dei moduli è ordinato in base al loro peso e nome file; quando due moduli hanno lo stesso peso, il primo modulo che appare nell'elenco è quello che viene in ordine alfabetico per primo.
Inoltre, qualsiasi implementazione del modulo hook_module_implements_alter()
può modificare l'ordine di invocazione degli hook.
Per questo motivo, non si deve supporre di sapere in quale ordine vengono richiamati gli hook.
Se lo scopo del codice sta modificando la route implementata da un altro modulo, ad esempio perché una route dovrebbe essere rimossa quando un secondo modulo è installato e abilitato, il codice dovrebbe usare hook_menu_alter()
. Se stai cercando di capire quale modulo "vincerebbe" in caso di conflitti di rotta, preferirei evitare tale conflitto di rotta e definire una rotta che non è già definita da un altro modulo.
Se poi stai implementando hook_menu_alter()
, e vuoi essere sicuro che il tuo modulo sia eseguito per ultimo, per essere il modulo che ha effettivamente la precedenza su una route, dovresti implementarlo hook_module_implements_alter()
anche tu .
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;
}
}