drupal 7 – Si dos módulos definieron la misma ruta de menú en 'hook_menu', ¿cuál elegirá Drupal?

Pregunta:

Por ejemplo, "moduleone" define la ruta 'admin / hello', que da como resultado print_moduleone_stuff() .

/**
 * Implements hook_menu()
 */
function moduleone_menu() {
  $items['admin/hello'] = array(
    'title' => 'Module One Hello World',
    'page callback' => print_moduleone_stuff,
  );
  return $items;
}

"moduletwo" define la ruta 'admin / hello', que 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;
}

Ambos módulos definieron la ruta 'admin / hello' para un resultado diferente. Con estos dos módulos habilitados, ¿cómo selecciona Drupal uno que otro? ¿Cómo resuelve Drupal el conflicto?

Respuesta:

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 de 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 De forma predeterminada, los módulos se ordenan por peso y nombre de archivo, si se configura esta opción en TRUE , la lista de módulos se ordenará por nombre de módulo.

Dado que menu_router_build() no pasa el segundo parámetro a menu_implements() , la función usa 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 primero alfabéticamente.

Además, cualquier módulo que implemente hook_module_implements_alter() puede alterar el orden en que se invocan los hooks.

Por esta razón, no debe asumir 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 usar hook_menu_alter() . Si está tratando de entender qué módulo "ganaría" en el caso de conflictos de ruta, preferiría evitar tal conflicto de ruta y definir una ruta que no esté ya definida desde otro módulo.

Si está implementando hook_menu_alter() , y desea asegurarse de que su módulo se ejecute en último lugar, para que sea 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;
  }
}

Leave a Comment

Your email address will not be published.

Scroll to Top

istanbul avukat

-

web tasarım