La fonction appelanthook_menu()
est menu_router_build () , appelée par menu_rebuild () . Il contient le code suivant.
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);
S'il y a deux modules définissant la même route, le dernier module du tableau renvoyé par module_implements()
remplacera la valeur définie à partir des autres modules.
Le deuxième paramètre requis par module_implements()
est défini comme:
$sort
Par défaut, les modules sont classés par poids et par nom de fichier, les paramètres de cette option sur TRUE
, la liste des modules seront classés par nom de module.
Puisque menu_router_build()
ne transmet pas le deuxième paramètre à menu_implements()
, la fonction utilise la valeur par défaut pour ce paramètre. Cela signifie que la liste des modules est classée selon leur poids et leur nom de fichier; lorsque deux modules ont le même poids, le premier module qui apparaît dans la liste est celui qui vient en premier par ordre alphabétique.
De plus, tout module implémentant hook_module_implements_alter()
peut modifier l'ordre d'appel des hooks.
Pour cette raison, vous ne devez pas supposer de savoir dans quel ordre les hooks sont appelés.
Si le but du code est de modifier l'itinéraire implémenté par un autre module, par exemple parce qu'un itinéraire doit être supprimé lorsqu'un deuxième module est installé et activé, le code doit utiliser hook_menu_alter()
. Si vous essayez de comprendre quel module gagnerait dans le cas de conflits de route, je préfère éviter un tel conflit de route et définir une route qui n'est pas déjà définie à partir d'un autre module.
Si vous implémentez hook_menu_alter()
, et que vous voulez être sûr que votre module est exécuté en dernier, pour être le module qui remplace efficacement un itinéraire, vous devez hook_module_implements_alter()
également l' implémenter .
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()
n'est pas utilisé pour définir de nouveaux menus, mais pour modifier ceux existants. Si deux modules modifient le même menu, l'altération qui survit est celle du module qui est exécutée en dernier.Quel que soit le module ayant une
weight
valeur inférieure dans lesystem
tableau, il sera appelé en premier, donc le module avec laweight
valeur la plus élevée «gagnera» dans ce cas.Si les poids sont les mêmes pour deux modules (ou plus), je crois qu'il n'y a pas de commande spécifique faite à part la commande qui vient directement de la table MySQL (je peux me tromper cependant).
Comme les résultats de retour de l'invocation de
hook_menu
sont simplement placés dans un seul tableau d'éléments de menu, il n'y aura jamais de «conflit» en tant que tel, les résultats des appels ultérieurs àhook_menu
remplaceront simplement ceux des appels précédents.la source
module_implements()
obtientFALSE
comme deuxième paramètre, mais fonctionne comme l'module_invoke_all()
appelle avec juste un paramètre.