Khi một web-browser tạo một request đến Drupal, nó đưa cho Drupal 1 URL, từ thông tin này Drupal “suy nghĩ” để chạy code và giải quyết request. Điều này được gọi là “dispatching”. Để làm điều này, drupal thực hiện như sau : yêu cầu các module cung cấp 1 mảng menu các item, đó là đường dẫn và các thông tin về đường dẫn...
Ví dụ : ta xây dựng 1 menu đơn giản : tạo một thư mục ttpmenu và tạo 2 file sau (y như cách xây dựng 1 module) : File : ttpmenu.info
Code: Chọn hết ; $Id$ name =ttpmenu description = add a menu to navigation block. package = ttpmenu. version = "1.0"
File : ttpmenu.module
Code: Chọn hết <?php // $Id$ /** * Implementation of hook_menu(). */ function ttpmenu_menu($may_cache) { // Create an array to hold the menu items we'll define. $items = array(); if ($may_cache) { // Define a static menu item. $items[] = array( 'title' => t('Title of TTP menu'), 'path' => 'ttpmenu', 'callback' => 'ttpmenu_hello', 'access' => TRUE ); } return $items; }
Sau đó chép cái thư mục này vào drupal/sites/all/modules. Chú ý : có thể thư mục modules sẽ ko có, bạn sẽ cần phải tạo nó.
- Hàm hook _menu thật sự sẽ được gọi 2 lần : một lần khi biến $may_cache được set là TRUE và một lần khi biến $may_cache được set là FALSE. Menu mà chúng ta tạo ra trong trường hợp là menu tĩnh. Nó không bào giờ thay đổi vì nó luôn là cachable.
- Toàn bộ cây menu chỉ được tạo 1 lần cho user, Drupal sẽ lưu cây này trong cache dưới dạng mảng trong bảng cache_menu.
- Nếu bạn muốn tạo một menu động, ta sẽ xử lý nó trong trường hợp biến $may_cache = FALSE.
- THAM SỐ CHO HÀM CALLBACK.
Đôi khi bạn muốn cung cấp thêm tham số cho hàm để nó “map” đến đường dẫn (path). Chúng ta thay đổi hàm callback của ví dụ ttpmenu như sau :
function ttpmenu_hello($name = NULL) { if (!isset($name)) { $name = "ThanhTu"; } return t('Hello @name!', array('@name' => $name)); }
- Bây giờ : nếu bạn request URL
http://localhost:81/drupal/?q=ttpmenu/ kếu quả sẽ là : Hello ThanhTu
-
Bây giờ : nếu bạn request URL http://localhost:81/drupal/?q=ttpmenu/Word kếu quả sẽ là : Hello Word
-
Bạn cũng có thể định nghĩa tham số bên trong hàm hook _menu thêm vào tham số cho hàm callback . Tham số mà bạn định nghĩa sẽ được truyền trước khi bất cứ tham số nào được gởi thông qua URL.
- Ví dụ :
Code: Chọn hết function ttpmenu_menu($may_cache) { $items = array(); if ($may_cache) { $items[] = array( 'title' => t('Hello'), 'path' => 'ttpmenu', 'callback' => 'ttpmenu_hello', 'callback arguments' => array(t('Hi!'), t('Ho!')), 'access' => TRUE ); } return $items; }
Code: Chọn hết function ttpmenu_hello($first, $second, $name = NULL) { // We just want to see what $first and $second are. drupal_set_message(t('First is %first', array('%first' => $first))); drupal_set_message(t('Second is %second', array('%second' => $second))); if (!isset($name)) { $name = t('ThanhTu'); } return t('Hello @name!', array('@name' => $name)); }
- Ở ví dụ ttp_menu, chúng ta chỉ mới định nghĩa 1 menu, bây giờ chúng ta thêm tiếp vào 1 cái nữa :
Code: Chọn hết function ttpmenu_menu($may_cache) { // Create an array to hold the menu items we'll define. $items = array(); if ($may_cache) { // Define a static menu item. $items[] = array( 'title' => t('Title of TTP menu'), 'path' => 'ttpmenu', 'callback' => 'ttpmenu_hello', 'access' => TRUE ); } $items[] = array( 'title' => t('TTP - Menu 2'), 'path' => 'ttpmenu/menu2', 'callback' => 'ttpmenu_menu2', 'access' => TRUE ); return $items; }
- ĐIỀU CHỈNH QUYỀN TRUY CẬP.
- Chúng ta sẽ phát triển tiếp ví dụ trên, ban đầu chúng ta thiết lập quyền truy cập accesss là TRUE, nghĩa là bất cứ ai cũng có thể truy cập vào menu của chúng ta. Thông thường quyền truy cập menu thường được điều khiển trong hàm hook _perm() và việc kiểm tra quyền truy cập thông qua hook user_access().
- Chúng ta sẽ định nghĩa một quyền truy cập gọi là receive greeting, nếu user không đủ quyền thì user sẽ nhận được một thông báo “Access denied”.
- Thêm vào ttpmenu.moudle đoạn code cài đặt hook _perm() :
Code: Chọn hết /** * Implementation of hook_perm(). */ function mymenu_perm() { return array('receive greeting'); }
- Bằng cách cài đặt hook _perm(), hệ thống menu của chúng ta sẽ có thể quyết định khi nào đường dẫn được truy cập và khi nào từ chối dựa vào vai trò của user.
- Khi quyết định quyền truy cập của một menu, Drupal sẽ nhìn vào khóa access thuộc đường dẫn đầy đủ (full-path) của menu. Nếu khóa access là TRUE nó sẽ được truy cập bất chấp khóa access của menu cha là FALSE. Nếu menu không có khóa access, Drupal sẽ đánh giá theo khóa access cha. Trường hợp ngay cả menu cha cũng không có khóa access, Drupal sẽ quay lui lại các nhánh trên cây cho đến khi nó tìm thấy khóa access (khóa access của gốc (root) luôn luôn là TRUE).
- Sau đây là bảng quyền truy cập của user với các khóa access :
Hình ảnh
- CÁC LOẠI MENU ITEM TRONG DRUPAL
- Khi bạn thêm vào một menu item trong hàm hook _menu(), bạn có thêm vào khóa type. Nếu bạn không định nghĩa khóa type, giá trị mặc định của khóa type là MENU_NORMAL_ITEM sẽ được dùng, Drupal sẽ xem đối xử với menu item của bạn khác nhau tùy theo khóa type mà bạn định nghĩa.
- Bảng mô tả các cờ (flag) của menu-item :
Hình ảnh
- Những hằng số thường sử dụng là : MENU_CALLBACK, MENU_LOCAL_TASK, và MENU_DEFAULT_LOCAL_TASK.
- ĐỊNH NGHĨA HÀM CALLBACK MÀ KHÔNG GẮN LINK VÀO MENU.
- Đôi khi bạn muốn “map” một URL đến một function mà không muốn tạo 1 menu item, bạn có thể làm điều này bằng cách khai báo khóa type là MENU_CALLBACK cho menu item của bạn.
- Ví dụ : chằng hạn trong node.moulde :
Code: Chọn hết $items[] = array( 'path' => 'rss.xml', 'title' => t('RSS feed'), 'callback' => 'node_feed', 'access' => user_access('access content'), 'type' => MENU_CALLBACK );
- THỂ HIỆN MENU DƯỚI DẠNG TAB.
- Hàm callback để thể hiện dưới dạng tab được gọi là local-task và nó có type là MENU_LOCAL_TASK, MENU_DEFAULT_LOCAL_TASK.
- Tựa đề của 1 local-task thường là một động từ ngắn (ví dụ : add, list...). Local-task thường dùng cho cho các đối tượng như node, user, workflow…
- Các local-task phải có 1 item cha theo thứ tự để tab có thể biểu diễn được.
- Ví dụ : tạo một local-task :
Code: Chọn hết /** * Implementation of hook_menu(). */ function milkshake_menu($may_cache) { $items = array(); if ($may_cache) { $items[] = array( 'path' => 'milkshake', 'title' => t('Milkshake flavors'), 'callback' => 'milkshake_overview', 'type' => MENU_CALLBACK ); $items[] = array( 'path' => 'milkshake/list', 'title' => t('List flavors'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'access' => user_access('list flavors'), 'weight' => 0 ); $items[] = array( 'path' => 'milkshake/add', 'title' => t('Add flavor'), 'callback' => 'milkshake_add', 'type' => MENU_LOCAL_TASK, 'access' => user_access('add flavor'), 'weight' => 1 ); $items[] = array( 'path' => 'milkshake/list/fruity', 'title' => t('Fruity flavors'), 'callback' => 'milkshake_list', 'type' => MENU_LOCAL_TASK, 'access' => user_access('list flavors'), ); $items[] = array( 'path' => 'milkshake/list/candy', 'title' => t('Candy flavors'), 'callback' => 'milkshake_list', 'type' => MENU_LOCAL_TASK, 'access' => user_access('list flavors'), ); } return $items; }
- Lưu ý : title của trang sẽ được lấy từ hàm callback cha, không phải là từ default local task, nếu bạn muốn có một title khác, bạn có thể sử dụng hàm drupal_set_title() để thay đổi.
Giao diện khi thực thi : Hình ảnh
- GHI ĐÈ CÁC HÀM GỌI MENU.
- Khi bạn cài đặt hook _menu trong module của bạn, không có gì ngăn chặn bạn thêm vào các entry đến các path của moudle khác hoặc thậm chí là override lại chúng. Đặc thù thì điều này sẽ được thực hiện trong menu.module, nó là một phần của Drupal nhưng bạn cũng có nhiều nguyên nhân để làm điều này bằng cách lập trình.
- Ví dụ : devel.module (là cái mà bạn chắc chắn sử dụng nếu bạn làm việc với Drupal development quan trọng), nó sẽ có một menu item để xóa các bảng Drupal’s cache. Chúng ta sẽ ghi đè các hàm để những hàm này được gọi đầu tiên. Trước tiên, chúng ta sẽ override devel.module menu item bằng cách chỉ rõ menu item của chúng ta cùng đường dẫn bên trong hàm hook _menu :
Code: Chọn hết /** * Implementation of hook_menu(). */ function mymodule_menu($may_cache) { $items = array(); if (!$may_cache && module_exist('devel')) { // Make sure devel.module is enabled. $items[] = array( 'path' => 'devel/cache/clear', // Same path that devel.module uses. 'title' => t('Wrap cache clear'), 'callback' => 'mymodule_clear_cache', 'type' => MENU_CALLBACK, 'access' => user_access('access devel information') // Same as devel.module. ); } }
-
XÓA MỘT MENU ĐÃ CÓ.
- Bằng cách dùng kỹ thuật “ghi đè” như trên, bạn có thể xóa 1 menu đã có sẵn bằng cách override lại đường dẫn (path) của chúng.
- Ví dụ : chúng ta muốn xóa menu Create Content và tính năng Add Content :
$items[] = array( 'path' => 'node/add', 'title' => t('This should not show up'), 'callback' => 'drupal_not_found', 'type' => MENU_CALLBACK ); Lúc này chức năng Create Content sẽ mất đi.
-
THÊM VÀO MỘT MENU SẴN CÓ.
- Bạn có thể thêm vào các menu có sẵn bằng cách thêm vào menu item với đường dẫn thông minh. Ví dụ : bạn muốn thêm 1 tab vào giao diện quản lý user của admin, bằng việc kiểm tra hook _menu của user.module, bạn xác định rằng đường dẫn amin/user là đường dẫn mà bạn muốn sử dụng cho menu item của mình :
$items[] = array( 'path' => 'admin/user/user/eradicate', 'title' => t('Eradicate all users'), 'callback' => 'ttpaddmenu_eradicate_users', 'type' => MENU_LOCAL_TASK, 'access' => user_access('eradicate users') ); }
Kết quả như sau : Hình ảnh
- CÁC LỖI THƯỜNG GẶP
Bạn đã cài đặt hook _menu() trong module của bạn nhưng hàm callback vẫn không được gọi, menu của bạn không thể hiện hoặc mọi thứ đều không làm việc? Sau đây là các lỗi phổ biến :
- Có phải bạn đã thiết lập khóa access cho một hàm và nó trả về FALSE?
- Bạn đã quên trả về mảng $items trong hook menu?
- Bạn đã xóa menu cache?
- Nếu bạn dùng một biểu thức để gán vào khóa path, kiểm tra xem việc đánh giá biểu thức có phải là đường dẫn này có hợp lệ?
- Nếu bạn thể hiện một menu item dưới dạng tab, bạn đã gán menu item cha để nó có hàm callback?
- Nếu bạn làm việc với local-task, bạn phải có ít nhất 2 tab trên một trang (đây là điều cần thiết đề nó xuất hiện).
- Nếu bạn thay đổi/ ghi đè/ xóa một path đã có sẵn, bạn có chắc rằng hook _menu() của bạn được gọi sau hook menu path mà bạn đã override.
|