Nếu cả hai mô-đun đều xác định cùng một đường dẫn menu trong 'hook_menu', thì một Drupal sẽ chọn cái nào?


14

Ví dụ: "moduleone" xác định đường dẫn 'admin / hello', đầu ra nào 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" xác định đường dẫn 'admin / hello', đầu ra nào 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;
}

Cả hai mô-đun được xác định đường dẫn 'admin / hello' cho kết quả khác nhau. Với hai mô-đun được kích hoạt, làm thế nào để Drupal chọn cái này hơn cái kia? Làm thế nào để Drupal giải quyết xung đột?

Câu trả lời:


16

Hàm gọi hook_menu()menu_router_build () , được gọi bởi menu numbuild () . Nó chứa mã sau đây.

  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);

Nếu có hai mô-đun xác định cùng một tuyến đường, mô-đun cuối cùng trong mảng được trả về module_implements()sẽ ghi đè giá trị được xác định từ các mô-đun khác.

Tham số thứ hai được yêu cầu bởi module_implements()được định nghĩa là:

$sortTheo mặc định, các mô-đun được sắp xếp theo trọng lượng và tên tệp, cài đặt tùy chọn này thành TRUE, danh sách mô-đun sẽ được sắp xếp theo tên mô-đun.

menu_router_build()không chuyển tham số thứ hai cho menu_implements(), nên hàm đang sử dụng giá trị mặc định cho tham số đó. Điều này có nghĩa là danh sách các mô-đun được sắp xếp theo trọng lượng và tên tệp của chúng; khi hai mô-đun có cùng trọng lượng, mô-đun đầu tiên xuất hiện trong danh sách là mô-đun xuất hiện theo thứ tự bảng chữ cái.

Hơn nữa, bất kỳ mô đun thực hiện nào hook_module_implements_alter()cũng có thể thay đổi thứ tự các hook được gọi.

Vì lý do này, bạn không nên giả định để biết thứ tự các móc được gọi.
Nếu mục đích của mã là thay đổi tuyến đường được thực hiện bởi một mô-đun khác, ví dụ vì tuyến đường sẽ bị xóa khi mô-đun thứ hai được cài đặt và kích hoạt, nên sử dụng mã hook_menu_alter(). Nếu bạn đang cố gắng hiểu mô-đun nào sẽ "chiến thắng" trong trường hợp xung đột tuyến đường, tôi thà tránh xung đột tuyến đường đó và xác định tuyến đường chưa được xác định từ mô-đun khác.

Nếu sau đó bạn đang triển khai hook_menu_alter()và bạn muốn chắc chắn mô-đun của mình được thực thi lần cuối, để trở thành mô-đun ghi đè một tuyến hiệu quả, bạn cũng nên thực hiện 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;
  }
}

Rất rõ ràng và hữu ích, cảm ơn. cũng cảm ơn vì đã đề cập đến việc sử dụng hook_menu_alter () trong trường hợp này.
gilzero

Điều gì xảy ra nếu hai mô đun xác định cùng một đường dẫn trong hook_menu_alter ()? quy tắc tương tự được áp dụng?
gilzero

hook_menu_alter()không được sử dụng để xác định các menu mới, nhưng để thay đổi các menu hiện có. Nếu hai mô-đun thay đổi cùng một menu, sự thay đổi còn tồn tại là mô-đun từ mô-đun được thực hiện lần cuối.
kiamlaluno

4

Bất kỳ mô-đun nào có weightgiá trị thấp hơn trong systembảng sẽ được gọi đầu tiên, vì vậy mô-đun có weightgiá trị cao hơn sẽ 'thắng' trong trường hợp này.

Nếu các trọng số là như nhau cho hai (hoặc nhiều) mô-đun, tôi tin rằng không có thứ tự cụ thể nào được thực hiện ngoài thứ tự xuất phát trực tiếp từ bảng MySQL (mặc dù tôi có thể sai về điều đó).

Vì kết quả trả về từ lệnh gọi hook_menuchỉ được đưa vào một mảng các mục menu, sẽ không bao giờ có "xung đột" như vậy, kết quả từ các cuộc gọi sau hook_menusẽ đơn giản ghi đè lên từ các cuộc gọi trước đó.


4
Theo Pro Drupal Development , các mô-đun có trọng lượng bằng nhau được gọi theo thứ tự bảng chữ cái theo tên hệ thống của chúng.
mpdon Arena

2
Những gì được báo cáo bởi cuốn sách đó là chính xác: Danh sách các mô-đun thực hiện một hook thường được sắp xếp theo trọng lượng và theo thứ tự abc; nó sẽ không được sắp xếp nếu module_implements()lấy FALSElàm tham số thứ hai, nhưng các chức năng như module_invoke_all()gọi nó chỉ bằng một tham số.
kiamlaluno

Nhận xét trước đây của tôi không hoàn toàn chính xác. Những gì tôi báo cáo trong câu trả lời của tôi là chính xác.
kiamlaluno
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.