たとえば、 "moduleone"はprint_moduleone_stuff()
を出力するパス 'admin/hello'を定義します。
_/**
* Implements hook_menu()
*/
function moduleone_menu() {
$items['admin/hello'] = array(
'title' => 'Module One Hello World',
'page callback' => print_moduleone_stuff,
);
return $items;
}
_
「moduletwo」は、パス「admin/hello」を定義し、print_moduletwo_stuff()
を出力します。
_/**
* Implements hook_menu()
*/
function moduletwo_menu() {
$items['admin/hello'] = array(
'title' => 'Module Two Hello World',
'page callback' => print_moduletwo_stuff,
);
return $items;
}
_
両方のモジュールが異なる結果のために「admin/hello」パスを定義しました。これらの2つのモジュールを有効にして、Drupalを選択する方法は?どうやってDrupal競合を解決するのですか?
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()
によって返される配列の最後のモジュールは、他のモジュールから定義された値をオーバーライドします。
module_implements()
で必要な2番目のパラメーターは、次のように定義されます。
_
$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;
}
}
_
weight
テーブルでsystem
の値が小さい方のモジュールが最初に呼び出されるため、この場合、weight
の値が大きいモジュールが「勝ち」ます。
重みが2つ(またはそれ以上)のモジュールで同じである場合、MySQLテーブルから直接来る順序以外に、特定の順序付けは行われていないと思います(ただし、それについては間違っているかもしれません)。
hook_menu
の呼び出しからの戻り結果はメニュー項目の単一の配列に入れられるだけなので、そのような「競合」は決して発生しません。後でhook_menu
を呼び出した結果は、以前の呼び出し。