ฉันจะใช้ hook_menu () ได้อย่างไร


103

พื้นฐานของการดำเนินการhook_menu()คืออะไร?

ฉันต้องการที่จะเห็นข้อมูลพื้นฐานที่ครอบคลุมในคำถามเดียวเพื่อหลีกเลี่ยงการตอบคำถามที่คล้ายกัน แต่แตกต่างกันไปเรื่อย ๆ

คำตอบ:


148

ข้อมูลนี้เป็นข้อมูลที่ถูกต้องสำหรับ Drupal 6 และ 7 ใน Drupal 8 hook_menu()ได้ถูกแทนที่ด้วยระบบการกำหนดเส้นทางใหม่ ด้านล่างเราดำเนินการhook_menu()ในสามขั้นตอนง่ายๆ

ขั้นตอนแรก

สร้างโมดูลที่ว่างเปล่าตามคำแนะนำในวิธีการสร้างโมดูลที่ว่างเปล่า ในรหัสที่แสดงที่นี่ก็สันนิษฐานว่าโมดูลเป็นชื่อHelloWorld

ขั้นตอนที่สอง

เพิ่มรหัสต่อไปนี้ไปยังไฟล์โมดูล

/**
 * Implements hook_menu().
 */
function helloworld_menu() {
  $items['hello'] = array(
    'title' => 'Hello world!',
    'page callback' => 'helloworld_page',
    'access callback' => TRUE,
  );

  return $items;
}

/**
 * Page callback for /hello.
 */
function helloworld_page() {
  return 'Hello world!';
}

ขั้นตอนที่สาม

เปิดใช้งานโมดูลและเยี่ยมชมhttp://example.com/hello (แทนที่ example.com ด้วยชื่อโดเมนสำหรับเซิร์ฟเวอร์ของคุณ)
คุณควรเห็นข้อความ "Hello world!" แค่นั้นแหละ! คุณมีการhook_menu()ใช้งานอย่างสมบูรณ์ hook_menu()สิ่งต่อไปนี้ต่างๆหัวข้อขั้นสูงเพิ่มเติมเกี่ยวกับ โดยเฉพาะอย่างยิ่งคุณอาจต้องการอ่านเกี่ยวกับการอนุญาตเนื่องจากหน้าเว็บด้านบนจะสามารถดูได้โดยทุกคน

ข้อโต้แย้ง

หากคุณต้องการส่งผ่านข้อมูลเพิ่มเติมไปยังการเรียกกลับหน้าเว็บคุณสามารถใช้การขัดแย้งหน้าเพื่อให้บรรลุสิ่งนี้ อาร์กิวเมนต์ของหน้าควรเป็นอาร์เรย์ของอาร์กิวเมนต์เพื่อส่งผ่านไปยังการเรียกกลับหน้า หากมีการใช้จำนวนเต็มเป็นอาร์กิวเมนต์มันจะแสดงส่วนหนึ่งของ URL เริ่มต้นจาก 0 เพิ่มขึ้นหนึ่งครั้งสำหรับแต่ละเครื่องหมายทับ (/) ในตัวอย่างต่อไปนี้หมายถึง 0 จะกลายเป็น 'สวัสดี'

function helloworld_menu() {
  $items['hello'] = array(
    'page callback' => 'helloworld_page',
    'page arguments' => array(0),
  );

  return $items;
}

function helloworld_page($argument1) {
  return $argument1;
}

สตริงจะถูกส่งเป็นคำต่อคำดังนั้นarray(0, 'world')อาจใช้เพื่อhello worldออกไปอีกครั้ง

function helloworld_page($argument1, $argument2) {
  return $argument1 . ' ' . $argument2;
}

"Wildcards" สามารถใช้เพื่อยอมรับข้อมูลโดยพลการจาก URL

function helloworld_menu() {
  $items['hello/%'] = array(
    'page callback' => 'helloworld_page',
    'page arguments' => array(1),
  );

  return $items;
}

function helloworld_page($argument1) {
  return $argument1;
}

เยี่ยมชมทักทาย / โลกจะเท่ากับ$argument1world

อาร์กิวเมนต์การโหลดอัตโนมัติ

บ่อยครั้งที่อาร์กิวเมนต์ URL จะเป็นหมายเลขที่ระบุตัวอย่างเช่นเอนทิตี เพื่อหลีกเลี่ยงการทำซ้ำรหัสที่แปลง ID นี้เป็นวัตถุที่สอดคล้องกัน Drupal สนับสนุนการโหลดอัตโนมัติสำหรับสัญลักษณ์ "ชื่อ" เมื่อใช้ wildcard ที่มีชื่อ Drupal จะตรวจสอบฟังก์ชั่นที่มีชื่อเดียวกับ wildcard ซึ่ง_loadต่อท้ายด้วย หากพบฟังก์ชันดังกล่าวฟังก์ชันจะถูกเรียกพร้อมกับค่าของค่าใน URL และสิ่งใดก็ตามที่ส่งคืนโดยฟังก์ชันโหลดเดอร์จะถูกส่งผ่านไปยังการเรียกกลับหน้าแทนที่ค่าเดิม เนื่องจาก Drupal มีฟังก์ชั่นดังกล่าวสำหรับการโหลดโหนดnode_load()เราสามารถรับโหนดที่โหลดอัตโนมัติและส่งผ่านไปยังการเรียกกลับหน้าเว็บ

function helloworld_menu() {
  $items['hello/%node'] = array(
    'page callback' => 'helloworld_page',
    'page arguments' => array(1),
  );

  return $items;
}

function helloworld_page($node) {
  return t('Hello node (ID = !nid)', array('!nid' => $node->nid));
}

การโหลดอัตโนมัติขั้นสูง

บางครั้งจำเป็นต้องโหลดอัตโนมัติมากขึ้นตามอาร์กิวเมนต์มากกว่าหนึ่งข้อ เนื่องจากอาร์กิวเมนต์ที่ตั้งชื่อเท่านั้นที่ถูกส่งไปยังโหลดเดอร์โดยค่าเริ่มต้นเราจึงต้องบอก Drupal อย่างชัดเจนว่าอาร์กิวเมนต์ใดที่โหลดพิเศษควรถูกส่งผ่านไปยังโหลดเดอร์ ตัวอย่างเช่นในการโหลดการแก้ไขที่เฉพาะเจาะจงของโหนดมีความจำเป็นต้องส่งผ่านไปยังnode_load()ID ของโหนดและรหัสการแก้ไข ที่สามารถทำได้โดยใช้รหัสต่อไปนี้

function helloworld_menu() {
  $items['hello/%node/revision/%'] = array(
    'page callback' => 'helloworld_page',
    'page arguments' => array(1),
    'load arguments' => array(3),
  );

  return $items;
}

function helloworld_page($node) {
  return t('Hello node (ID = !nid, revision ID = !rid)', array('!nid' => $node->nid, '!rid' => $node->vid));
}

สิทธิ์

'access callback' => TRUE,จำเป็นต้องทำให้ตัวอย่างง่าย ๆ ข้างต้นสามารถดูได้ แต่แทบจะไม่สมบูรณ์แบบเพราะไม่สามารถควบคุมได้เลย ทุกคนที่พยายามเข้าชม / สวัสดีจะได้รับสิทธิ์การเข้าถึง วิธีที่ง่ายที่สุดในการจัดเตรียมการควบคุมบางอย่างคือการให้การเรียกกลับการเข้าถึงเหมือนกับการเรียกกลับหน้าเว็บจากด้านบน รหัสต่อไปนี้ยังอนุญาตให้เข้าถึงทุกคน แต่แสดงวิธีย้ายตรรกะไปยังฟังก์ชันที่เรียกว่า ณ เวลาเข้าถึงจึงช่วยให้ตรรกะที่ซับซ้อนมากขึ้น

/**
 * Implements hook_menu().
 */
function helloworld_menu() {
  $items['hello'] = array(
    'page callback' => 'helloworld_page',
    'access callback' => 'helloworld_access',
  );

  return $items;
}

/**
 * Access callback for /hello.
 */
function helloworld_access() {
  return TRUE;
}

นี่ไม่ใช่วิธีที่ดีที่สุดเนื่องจากการใช้ฟังก์ชั่นที่กำหนดเองมักจะซ้ำซ้อนโดยไม่จำเป็นต้องใช้รหัส วิธีที่ดีกว่าคือการใช้งานเป็นส่วนuser_access()ใหญ่ ร่วมกันเรียกกลับเข้าถึงมันเป็นไปได้ที่จะตั้งข้อโต้แย้งการเข้าถึง มันเป็นไปได้ที่จะต้องมีหน้าเพื่อให้สามารถดูได้จากผู้ใช้ที่มีสิทธิ์การเข้าถึงโปรไฟล์ผู้ใช้ด้วยรหัสต่อไปนี้

/**
 * Implements hook_menu().
 */
function helloworld_menu() {
  $items['hello'] = array(
    'page callback' => 'helloworld_page',
    'access callback' => 'user_access',
    'access arguments' => array('access user profiles'),
  );

  return $items;
}

เนื่องจากการเรียกกลับโดยค่าเริ่มต้นคือ user_access สามารถออกได้เช่นเดียวกับในรหัสด้านบน

หัวข้อขั้นสูงเพิ่มเติม

hook_menu()เอกสารอย่างเป็นทางการให้ข้อมูลเพิ่มเติมเกี่ยวกับกรณีการใช้งานที่ซับซ้อนที่สุดสำหรับตะขอ


3
น่ากลัว! เพียงเพื่อความสมบูรณ์ของtitleคุณสมบัติที่จำเป็นสำหรับรายการทั้งหมดกลับมาจากhook_menu()
ไคลฟ์

1
ฉันรู้ว่าเอกสารพูดอย่างนั้น แต่เมื่อฉันทดสอบใน D7 นั่นไม่ใช่กรณี ฉันจะเพิ่มเข้าไปในตัวอย่างแรกผมคิดว่า แต่ผมอยากให้สิ่งที่แน่นอนขั้นต่ำที่จะทำให้มันเป็นไปอย่างง่ายดาย
Letharion

1
ฉันจะบอกว่าการเพิ่มชื่อลงในหน้าเป็นหนึ่งในสิ่งที่น้อยที่สุดที่คุณสามารถทำได้เกี่ยวกับ hook_menu () แต่มันเป็นโพสต์ของคุณ: P อาจคุ้มค่าที่จะแก้ไขข้อผิดพลาดทางไวยากรณ์ (โค้ดตัวอย่าง 2, 4, 5 & 6) เพื่อให้ผู้คนสามารถคัดลอกและวาง
ไคลฟ์

1
Argh ฉันเริ่มขยันในการใช้งานรหัสจริง แต่เมื่อเวลาผ่านไปฉันก็ยิ่งใหญ่และเริ่มทำสำเนา แก้ไขข้อผิดพลาดทางไวยากรณ์อย่างน้อยที่ฉันเห็น;) ดีคุณถูกต้องว่าควรมีชื่อเรื่องของหลักสูตรดังนั้นฉันได้เพิ่มหนึ่งในตัวอย่างเริ่มต้น
Letharion

1
ฉันจะลงทะเบียนไฟล์ php ไปยังเส้นทางโดยใช้ hook_menu ได้อย่างไร มันเป็นไฟล์ php ที่เขียนขึ้นเองซึ่งรวมถึง drupal bootstrap ใช้ตัวแปรเซสชัน drupal และยอมรับอาร์กิวเมนต์ซึ่งเป็นรหัสผู้ใช้
ЕлинЙ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.