หากทั้งสองโมดูลกำหนดเส้นทางเมนูเดียวกันใน 'hook_menu' Drupal อันใดจะเลือก


14

ยกตัวอย่างเช่น "moduleone" กำหนดเส้นทาง 'admin / สวัสดี' 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 / สวัสดี' 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' เพื่อผลลัพธ์ที่แตกต่าง เมื่อเปิดใช้งานโมดูลทั้งสองนี้ 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()สามารถแก้ไขลำดับของ hooks ที่ถูกเรียกใช้

ด้วยเหตุผลนี้คุณไม่ควรสันนิษฐานว่าลำดับใดถูกเรียกใช้ hooks ถ้าวัตถุประสงค์ของรหัสที่จะเปลี่ยนแปลงเส้นทางที่ดำเนินการโดยโมดูลอื่นตัวอย่างเช่นเพราะเป็นเส้นทางที่ควรจะถูกลบออกเมื่อโมดูลที่สองมีการติดตั้งและเปิดใช้งานรหัสควรใช้
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;
  }
}

ชัดเจนและเป็นประโยชน์ขอบคุณ ขอบคุณสำหรับการกล่าวถึงการใช้งาน hook_menu_alter () ในกรณีนี้
gilzero

เกิดอะไรขึ้นถ้าสองโมดูลกำหนดเส้นทางเดียวกันใน hook_menu_alter () ใช้กฎเดียวกันหรือไม่
gilzero

hook_menu_alter()ไม่ได้ใช้เพื่อกำหนดเมนูใหม่ แต่เปลี่ยนเมนูที่มีอยู่ หากโมดูลสองรายการเปลี่ยนเมนูเดียวกันการเปลี่ยนแปลงที่มีชีวิตอยู่นั้นเป็นสิ่งที่มาจากโมดูลที่ดำเนินการเป็นครั้งสุดท้าย
kiamlaluno

4

โมดูลใดก็ตามที่มีweightค่าต่ำกว่าในsystemตารางจะถูกเรียกก่อนดังนั้นโมดูลที่มีweightมูลค่าสูงกว่าจะ 'ชนะ' ในกรณีนี้

หากน้ำหนักเท่ากันสำหรับสองโมดูล (หรือมากกว่า) ฉันเชื่อว่าไม่มีการสั่งซื้อที่เฉพาะเจาะจงนอกเหนือจากการสั่งซื้อที่มาโดยตรงจากตาราง MySQL (ฉันอาจผิดเกี่ยวกับเรื่องนั้น)

เนื่องจากผลลัพธ์ที่ส่งคืนจากการเรียกใช้hook_menuจะถูกใส่ลงในอาร์เรย์ของรายการเมนูเดียวจะไม่มี 'ความขัดแย้ง' เช่นนี้ผลลัพธ์จากการโทรในภายหลังเพื่อhook_menuจะแทนที่สิ่งเหล่านั้นจากการโทรก่อนหน้านี้


4
ตามการพัฒนาของ Dr Dralโมดูลที่มีน้ำหนักเท่ากันถูกเรียกตามลำดับตัวอักษรตามชื่อระบบ
mpdonadio

2
สิ่งที่รายงานโดยหนังสือเล่มนั้นถูกต้อง: รายการของโมดูลที่ใช้เบ็ดนั้นโดยทั่วไปแล้วจะเรียงตามน้ำหนักและตัวอักษร; มันจะไม่ถูกจัดเรียงหากmodule_implements()ได้รับFALSEเป็นพารามิเตอร์ที่สอง แต่ฟังก์ชั่นเช่นmodule_invoke_all()เรียกมันว่ามีเพียงพารามิเตอร์
kiamlaluno

ความคิดเห็นก่อนหน้าของฉันไม่ถูกต้องทั้งหมด สิ่งที่ฉันรายงานในคำตอบของฉันถูกต้อง
kiamlaluno
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.