La función que invoca hook_menu()
es menu_router_build () , llamada por menu_rebuild () . Contiene el siguiente código.
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);
Si hay dos módulos que definen la misma ruta, el último módulo en la matriz devuelto por module_implements()
anulará el valor definido de los otros módulos.
El segundo parámetro requerido por module_implements()
se define como:
$sort
Por defecto, los módulos se ordenan por peso y nombre de archivo, la configuración de esta opción TRUE
, la lista de módulos se ordenará por nombre de módulo.
Como menu_router_build()
no pasa el segundo parámetro a menu_implements()
, la función está usando el valor predeterminado para ese parámetro. Esto significa que la lista de módulos está ordenada por su peso y nombre de archivo; cuando dos módulos tienen el mismo peso, el primer módulo que aparece en la lista es el que aparece alfabéticamente primero.
Además, la implementación de cualquier módulo hook_module_implements_alter()
puede alterar el orden en que se invocan los ganchos.
Por este motivo, no debe suponer que sabe en qué orden se invocan los ganchos.
Si el propósito del código es alterar la ruta implementada por otro módulo, por ejemplo, porque una ruta debe eliminarse cuando se instala y habilita un segundo módulo, el código debe usarse hook_menu_alter()
. Si está tratando de entender qué módulo "ganaría" en el caso de conflictos de ruta, prefiero evitar dicho conflicto de ruta y definir una ruta que no esté definida desde otro módulo.
Si luego está implementando hook_menu_alter()
, y desea asegurarse de que su módulo se ejecute en último lugar, para ser el módulo que anule efectivamente una ruta, también debe implementar 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()
no se usa para definir nuevos menús, sino para modificar los existentes. Si dos módulos alteran el mismo menú, la alteración que sobrevive es la del módulo que se ejecuta para el final.El módulo que tenga un
weight
valor más bajo en lasystem
tabla se llamará primero, por lo que el módulo con elweight
valor más alto 'ganará' en este caso.Si los pesos son los mismos para dos (o más) módulos, creo que no se realiza un pedido específico que no sea el pedido que proviene directamente de la tabla MySQL (aunque podría estar equivocado al respecto).
Como los resultados de retorno de la invocación de
hook_menu
simplemente se colocan en una sola matriz de elementos de menú, nunca habrá un 'conflicto' como tal, los resultados de llamadas posterioreshook_menu
simplemente anularán los de las llamadas anteriores.fuente
module_implements()
obtieneFALSE
como segundo parámetro, pero funciona como lomodule_invoke_all()
llama con solo un parámetro.