Якщо обидва модулі визначають один і той же шлях до меню в "кука_меню", який з них вибере Drupal?


14

Наприклад, "moduleone" визначає шлях "admin / hello", який виводиться 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" визначає шлях "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;
}

Обидва модулі визначали шлях "адмін / привіт" для різних результатів. Як увімкнено ці два модулі, як Drupal вибирає один, ніж інший? Як Drupal вирішує конфлікт?

Відповіді:


16

Виклик функції 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);

Якщо є два модулі, що визначають один і той же маршрут, останній модуль у масиві, повернутий за допомогою module_implements(), перекриє значення, визначене з інших модулів.

Другий необхідний параметр module_implements()визначається як:

$sortЗа замовчуванням модулі упорядковуються за вагою та назвою файлу, налаштовуючи цю опцію TRUE, список модулів буде упорядкований за назвою модуля.

Оскільки menu_router_build()другий параметр не передає menu_implements(), функція використовує для цього параметра значення за замовчуванням. Це означає, що список модулів упорядкований за їх вагою та назвою файлу; коли два модулі мають однакову вагу, перший модуль, який з’являється у списку, є тим, що в алфавітному порядку стає першим.

Крім того, будь-який реалізуючий модуль hook_module_implements_alter()може змінити порядок виклику гачків.

З цієї причини ви не повинні припускати, що знаєте, в якому порядку викликаються гачки.
Якщо метою коду є зміна маршруту, реалізованого іншим модулем, наприклад, тому що маршрут слід видалити, коли другий модуль встановлений і включений, код повинен використовувати 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;
  }
}

так чітко і корисно, дякую. також дякуємо, що згадували про використання в цій справі гачку_menu_alter ().
gilzero

що робити, якщо два модулі визначають один і той же шлях у moll_menu_alter ()? застосовуються ті самі правила?
gilzero

hook_menu_alter()використовується не для визначення нових меню, а для зміни існуючих. Якщо два модулі змінюють одне і те ж меню, зміни, що вижили, - це модуль, який виконується останнім часом.
kiamlaluno

4

Залежно від того, який модуль має нижче weightзначення, systemтаблиця буде називатися першою, тому модуль з більшим weightзначенням у цьому випадку буде «виграш».

Якщо ваги однакові для двох (або більше) модулів, я вважаю, що немає іншого замовлення, окрім замовлення, що надходить безпосередньо з таблиці MySQL (я можу помилитися з цього приводу).

Оскільки результати повернення після виклику hook_menuпросто поміщаються в один масив пунктів меню, ніколи не буде конфлікту як такого, результати пізніших викликів hook_menuпросто перевершать ті з попередніх викликів.


4
Згідно з програмою Pro Drupal Development , модулі з однаковою вагою викликаються в алфавітному порядку за назвою системи.
mpdonadio

2
Те, що повідомляється в цій книзі, є правильним: Список модулів, що реалізують гачок, як правило, сортується за вагою та в алфавітному порядку; він би не сортувався, якщо module_implements()отримує FALSEяк другий параметр, але функціонує як module_invoke_all()виклик його просто параметром.
kiamlaluno

Мій попередній коментар не зовсім точний. Те, що я повідомляю у своїй відповіді, є правильним.
kiamlaluno
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.