関数呼び出しがhook_menu()
あるmenu_router_build()によって呼び出され、menu_rebuild() 。次のコードが含まれています。
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);
同じルートを定義するモジュールが2つある場合、配列によって返される最後のモジュールはmodule_implements()
、他のモジュールから定義された値をオーバーライドします。
で必要な2番目のパラメーターmodule_implements()
は次のように定義されます。
$sort
デフォルトでは、モジュールは重みとファイル名で並べ替えられ、このオプションをTRUE
に設定すると、モジュールリストはモジュール名で並べ替えられます。
にmenu_router_build()
2番目のパラメーターを渡さないためmenu_implements()
、関数はそのパラメーターのデフォルト値を使用しています。これは、モジュールのリストがその重みとファイル名の順に並べられることを意味します。2つのモジュールの重量が同じ場合、リストに表示される最初のモジュールがアルファベット順に最初に表示されます。
さらに、実装hook_module_implements_alter()
するモジュールは、フックが呼び出される順序を変更できます。
このため、フックが呼び出される順序を知ることを想定しないでください。
コードの目的が別のモジュールによって実装されたルートを変更することである場合、たとえば、2番目のモジュールをインストールして有効にしたときにルートを削除する必要がある場合、コードはを使用する必要がありますhook_menu_alter()
。ルート競合の場合にどのモジュールが「勝つ」かを理解しようとする場合、そのようなルート競合を避け、別のモジュールからまだ定義されていないルートを定義します。
その後、を実装していてhook_menu_alter()
、モジュールが最後に実行され、ルートを効果的にオーバーライドするモジュールになるようにしたい場合は、実装する必要があり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;
}
}