Die aufrufende Funktion hook_menu()
ist menu_router_build () , die von menu_rebuild () aufgerufen wird . Es enthält den folgenden Code.
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);
Wenn zwei Module dieselbe Route definieren, module_implements()
überschreibt das letzte Modul in dem von zurückgegebenen Array den von den anderen Modulen definierten Wert.
Der zweite erforderliche Parameter module_implements()
ist wie folgt definiert:
$sort
Standardmäßig werden die Module nach Gewicht und Dateiname sortiert. Die Einstellungen für diese Option werden in der Modulliste nach TRUE
Modulnamen sortiert.
Da menu_router_build()
der zweite Parameter nicht an übergeben wird menu_implements()
, verwendet die Funktion den Standardwert für diesen Parameter. Dies bedeutet, dass die Liste der Module nach Gewicht und Dateiname sortiert ist. Wenn zwei Module das gleiche Gewicht haben, wird in der Liste als erstes Modul das Modul angezeigt, das alphabetisch an erster Stelle steht.
Darüber hinaus kann jede hook_module_implements_alter()
Modulimplementierung die Reihenfolge ändern, in der die Hooks aufgerufen werden.
Aus diesem Grund sollten Sie nicht davon ausgehen, dass Sie wissen, in welcher Reihenfolge die Hooks aufgerufen werden.
Wenn der Zweck des Codes darin besteht, die von einem anderen Modul implementierte Route zu ändern, z. B. weil eine Route entfernt werden soll, wenn ein zweites Modul installiert und aktiviert wird, sollte der Code verwendet werden hook_menu_alter()
. Wenn Sie versuchen zu verstehen, welches Modul bei Routenkonflikten "gewinnen" würde, würde ich einen solchen Routenkonflikt lieber vermeiden und eine Route definieren, die noch nicht von einem anderen Modul definiert wurde.
Wenn Sie dann implementieren hook_menu_alter()
und sicherstellen möchten, dass Ihr Modul zuletzt ausgeführt wird, sollten Sie auch implementieren , um das Modul zu sein, das eine Route effektiv überschreibt 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()
wird nicht verwendet, um neue Menüs zu definieren, sondern um die vorhandenen zu ändern. Wenn zwei Module dasselbe Menü ändern, bleibt nur die Änderung des Moduls übrig, das zuletzt ausgeführt wurde.Welches Modul
weight
in dersystem
Tabelle einen niedrigeren Wert hat, wird zuerst aufgerufen.weight
In diesem Fall gewinnt das Modul mit dem höheren Wert.Wenn die Gewichte für zwei (oder mehr) Module gleich sind, gibt es meines Erachtens keine andere bestimmte Reihenfolge als die, die direkt aus der MySQL-Tabelle stammt (ich könnte mich jedoch irren).
Da die Rückgabeergebnisse beim Aufrufen von
hook_menu
nur in einem Array von Menüelementen zusammengefasst werden, kommt es nie zu einem „Konflikt“. Die Ergebnisse späterer Aufrufe von bishook_menu
überschreiben einfach die Ergebnisse früherer Aufrufe.quelle
module_implements()
bekommtFALSE
als zweiter Parameter, aber Funktionen wiemodule_invoke_all()
Anrufe mit nur einem Parameter.