A função que chamahook_menu()
é menu_router_build () , chamada por menu_rebuild () . Ele contém o seguinte 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);
Se houver dois módulos definindo a mesma rota, o último módulo na matriz retornado por module_implements()
substituirá o valor definido dos outros módulos.
O segundo parâmetro exigido por module_implements()
é definido como:
$sort
Por padrão, os módulos são ordenados por peso e nome do arquivo, as configurações dessa opção para TRUE
, lista de módulos serão ordenadas pelo nome do módulo.
Como menu_router_build()
não passa o segundo parâmetro para menu_implements()
, a função está usando o valor padrão para esse parâmetro. Isso significa que a lista de módulos é ordenada por peso e nome de arquivo; quando dois módulos têm o mesmo peso, o primeiro módulo que aparece na lista é o primeiro em ordem alfabética.
Além disso, qualquer módulo implementado hook_module_implements_alter()
pode alterar a ordem em que os ganchos são chamados.
Por esse motivo, você não deve saber em qual ordem os ganchos são chamados.
Se o objetivo do código for alterar a rota implementada por outro módulo, por exemplo, porque uma rota deve ser removida quando um segundo módulo é instalado e ativado, o código deve ser usado hook_menu_alter()
. Se você está tentando entender qual módulo "venceria" no caso de conflitos de rota, prefiro evitar esse conflito de rota e definir uma rota que ainda não esteja definida em outro módulo.
Se você está implementando hook_menu_alter()
e deseja garantir que seu módulo seja executado por último, para ser o módulo que efetivamente substitui uma rota, você deve implementar hook_module_implements_alter()
também.
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ão é usado para definir novos menus, mas para alterar os existentes. Se dois módulos alteram o mesmo menu, a alteração que sobrevive é a do módulo executado por último.O módulo que tiver um
weight
valor mais baixo nasystem
tabela será chamado primeiro, portanto, o módulo com oweight
valor mais alto 'vencerá' neste caso.Se os pesos são os mesmos para dois (ou mais) módulos, acredito que não há nenhuma ordem específica feita além da ordem que vem diretamente da tabela MySQL (eu poderia estar errado sobre isso).
Como os resultados de retorno da chamada de
hook_menu
são apenas colocados em uma única matriz de itens de menu, nunca haverá um 'conflito' como tal, os resultados de chamadas posterioreshook_menu
simplesmente substituirão os das chamadas anteriores.fonte
module_implements()
receberFALSE
como segundo parâmetro, mas funciona como omodule_invoke_all()
chama apenas com um parâmetro.