Tôi nên triển khai hook_menu () như thế nào?


103

Các nguyên tắc cơ bản của việc thực hiện là hook_menu()gì?

Tôi muốn thấy những điều cơ bản được đề cập trong một câu hỏi duy nhất, để tránh phải trả lời những câu hỏi tương tự nhưng khác nhau lặp đi lặp lại.

Câu trả lời:


148

Thông tin này có giá trị cho Drupal 6 và 7. Trong Drupal 8, hook_menu()đã được thay thế bởi hệ thống định tuyến mới . Dưới đây chúng tôi thực hiện hook_menu()trong ba bước đơn giản.

Bước một

Tạo một mô-đun trống theo hướng dẫn trong Cách tạo mô-đun trống . Trong mã được hiển thị ở đây, giả sử mô-đun được đặt tên là hellowworld .

Bước hai

Thêm mã sau vào tệp mô-đun.

/**
 * 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!';
}

Bước thứ ba

Kích hoạt mô-đun và truy cập http://example.com/hello . (Thay thế example.com bằng tên miền cho máy chủ của bạn.)
Bạn sẽ thấy thông báo "Xin chào thế giới!". Đó là nó! Bạn có một hook_menu()thực hiện làm việc đầy đủ . Điều gì sau đây là các chủ đề nâng cao khác nhau liên quan đến hook_menu(). Cụ thể, bạn có thể muốn đọc về các quyền, vì bất kỳ ai ở trên trang cũng có thể xem được.

Tranh luận

Nếu bạn muốn truyền thêm dữ liệu cho cuộc gọi lại trang, bạn có thể sử dụng đối số trang để đạt được điều này. Đối số trang phải là một mảng các đối số để chuyển sang gọi lại trang. Nếu một số nguyên được sử dụng làm đối số, nó sẽ đại diện cho một phần của URL, bắt đầu từ 0, tăng một lần cho mỗi dấu gạch chéo (/). Trong ví dụ sau, điều này có nghĩa là 0 sẽ được chuyển thành 'xin chào'.

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

  return $items;
}

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

Chuỗi sẽ được gửi trên nguyên văn, vì vậy array(0, 'world')có thể được sử dụng để thoát hello worldra một lần nữa.

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

"Ký tự đại diện" có thể được sử dụng để chấp nhận dữ liệu tùy ý từ URL.

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

  return $items;
}

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

Tham quan xin chào / thế giới, $argument1sẽ bằng nhau world.

Đối số tự động tải

Thông thường, một đối số URL sẽ là số xác định, ví dụ: một thực thể. Để tránh sao chép mã chuyển đổi ID này thành đối tượng tương ứng, Drupal hỗ trợ tự động tải cho các ký tự đại diện "được đặt tên". Khi sử dụng ký tự đại diện có tên, Drupal sẽ kiểm tra chức năng có cùng tên với ký tự đại diện, có hậu tố _load. Nếu một hàm như vậy được tìm thấy, nó sẽ được gọi với giá trị của giá trị trong URL và bất cứ thứ gì được trả về bởi hàm nạp sẽ được chuyển đến hàm gọi lại trang thay cho giá trị ban đầu. Vì Drupal đã có chức năng như vậy để tải các nút, node_load()nên chúng tôi có thể nhận được các nút được tải tự động và chuyển đến cuộc gọi lại trang.

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

Tự động tải nâng cao

Đôi khi, sẽ cần phải tự động tải nhiều hơn dựa trên nhiều hơn một đối số. Do chỉ có đối số được đặt tên được truyền cho trình tải theo mặc định, nên người ta cần nói rõ cho Drupal biết các đối số tải thêm sẽ được truyền cho trình tải. Ví dụ, để tải một bản sửa đổi cụ thể của một nút, cần phải chuyển đến node_load()ID nút và ID sửa đổi. Điều đó có thể được thực hiện bằng mã sau đây.

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

Quyền

'access callback' => TRUE,là cần thiết để làm cho ví dụ đơn giản ở trên có thể xem được, nhưng nó hầu như không lý tưởng, vì nó không cho phép kiểm soát những gì đã từng có. Bất cứ ai cố gắng truy cập / xin chào sẽ được cấp quyền truy cập. Cách dễ nhất để cung cấp một số biện pháp kiểm soát, là cung cấp một cuộc gọi lại truy cập, giống như cuộc gọi lại trang từ phía trên. Đoạn mã sau vẫn cho phép truy cập vào bất kỳ ai, nhưng chỉ ra cách di chuyển logic đến một hàm được gọi tại thời điểm truy cập, do đó cho phép logic phức tạp hơn.

/**
 * 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;
}

Đây không hẳn là cách tốt nhất, vì sử dụng một chức năng tùy chỉnh thường sẽ không cần sao chép mã. Một cách tốt hơn sẽ là, hầu hết thời gian, để sử dụng user_access(). Cùng với cuộc gọi lại truy cập, có thể đặt đối số truy cập. Có thể yêu cầu trang có thể xem được từ người dùng với quyền truy cập hồ sơ người dùng với mã sau đây.

/**
 * 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;
}

Vì cuộc gọi lại truy cập theo mặc định là user_access, nên nó có thể bị bỏ qua, như trong đoạn mã trên.

Chủ đề nâng cao hơn

hook_menu()Tài liệu chính thức cung cấp nhiều thông tin hơn về các trường hợp sử dụng phức tạp nhất cho hook.


3
Tuyệt vời! Chỉ vì mục đích hoàn chỉnh, titletài sản được yêu cầu cho tất cả các mặt hàng được trả lại từhook_menu()
Clive

1
Tôi biết rằng các tài liệu nói như vậy, nhưng khi tôi thử nghiệm trong D7, đó không phải là trường hợp. Tôi có thể thêm nó vào ví dụ đầu tiên tôi đoán, nhưng tôi muốn giữ điều cần tuyệt đối tối thiểu để làm cho nó dễ dàng như có thể.
Letharion

1
Tôi muốn nói thêm tiêu đề vào một trang là một trong những điều tối thiểu tuyệt đối bạn có thể muốn làm với hook_menu () nhưng đó là bài đăng của bạn: P Có thể sửa lỗi lỗi cú pháp (ví dụ mã 2, 4, 5 & 6), vì vậy mọi người có thể sao chép và dán
Clive

1
Argh, ban đầu tôi rất siêng năng trong việc chạy mã, nhưng khi thời gian trôi qua, tôi trở nên chậm hơn và bắt đầu sao chép. Đã sửa các lỗi cú pháp, ít nhất là những lỗi tôi đã thấy;) Chà, bạn đúng rằng nên có một tiêu đề của khóa học, vì vậy tôi đã thêm một lỗi vào ví dụ ban đầu.
Letharion

1
Làm cách nào tôi có thể đăng ký tệp php vào đường dẫn bằng hook_menu? Nó là một tệp php được viết tùy chỉnh bao gồm bootstrap drupal, sử dụng các biến phiên drupal và chấp nhận một đối số là id người dùng.
ЕЕннн
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.