| Photoshop giúp chỉnh độ sáng và giúp làm những hình hơi tối sáng rõ ra, đồng thời cũng làm cho hình thật sắc nét một cách dễ dàng. Bức hình bên trái thiếu ánh sáng vì dù của đèn chớp flash để hơi xa và bị lệch (để tránh bị bóng). Hơn nữa bức hình bị lồng ánh sáng màu vàng của đèn halogen làm da mặt và quần áo người mẫu xạm đi. Dùng hệ thống "đường cong" sẽ làm cho màu vàng biến mất và hình sáng hẳn ra khiến màu sắc của bức hình lộng lẫy, tươi mát hơn. Sau đây là phần chỉ dẫn cách sử dụng kỹ thuật này để chỉnh ánh sáng cho những hình bị tối. | |
Hình nguyên thủy thiếu ánh sáng | Hình chỉnh với đường cong (tự động) |
Gõ chữ Ctrl và M để thấy mục Image/Adjustments/Curves (Hình/Chỉnh/Đường Cong). Bấm chọn nút Auto (tự động) là xong. Photoshop sẽ làm cho bức hình tối được sáng ra và ngược lại, nếu bức hình chụp sáng quá sẽ được làm tối lại.
| |
Trong các hệ thống đồ họa, độ sáng trong một bức hình, đi từ màu đen sang trắng, thường được diễn tả bằng một đường thẳng chéo 45 độ như trong hình dưới đây. Nếu độ sáng của một số chỗ trong hình được tăng lên để làm hình sáng ra, hay giảm đi để hình tối lại, đường thẳng này sẽ trở thành một "đường cong".
Trong hình học, các điểm nằm trên đường chéo 45 độ có tung độ và hoành độ cùng một giá trị. Điều này có nghĩa là độ sáng nguyên thủy (biểu hiện bằng hoành độ) không bị thay đổi khi vẽ lại (biểu hiện bằng tung độ). Trục hoành cho thấy độ sáng nguyên thủy, trong khi trục tung cho thấy độ sáng của các điểm màu sau khi được vẽ lại. Vì trục hoành và trục tung cho thấy các độ sáng từ đi từ 0 đến 255, các vị trí nằm ở bên ngoài và phía trên đường chéo diễn tả các điểm màu được vẽ lại với độ sáng chói hơn độ sáng nguyên thủy. Ngược lại, các vị trí nằm ở bên ngoài và phía dưới đường chéo diễn tả các điểm màu được vẽ lại với độ sáng tối hơn độ sáng nguyên thủy. Một bức hình có nhiều điểm màu xậm sẽ được làm sáng ra nếu tâm đường thẳng được kéo về góc tây bắc của hình vuông độ sáng. Danh từ "đường cong" này hay dùng để diễn tả cách chỉnh ánh sáng của một tấm hình bằng cách tăng lên hay giảm xuống độ sáng của một nhóm điểm màu có độ sáng giống nhau để tăng độ tương phản hay rõ nét của hình. Dùng đường cong cho các màu chính như đỏ, xanh, chàm hay lam, tím, vàng sẽ làm nổi bật hay dịu lại những màu tương phản trong hình. Kỹ thuật này rất hữu hiệu với những bức hình tuy bị tối nhưng có màu sắc tương phản rõ rệt. Hình thí dụ trên đây cho thấy sự tương phản của quốc phục màu xanh dương đậm và ghế đỏ với nền hình màu trắng. Nếu dùng phương pháp tự động mà độ sáng trong hình vẫn không được chỉnh đúng theo ý muốn, các bạn có thể bấm chuột vào giữa đường cong và kéo đường cong về hướng các đỉnh của hình vuông để chỉnh thêm. Các bạn nhớ chọn Preview để thấy ngay hình lúc sửa với độ sáng mới. | |
Thứ Năm, 11 tháng 9, 2014
chỉnh độ sáng và màu sắc
THIẾT KẾ WEBSITE DRUPAL CƠ BẢN: DRUPAL LÀ GÌ ?
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... Các bạn học Drupal có thể tham khảo một vài ví dụ sau để có thể tự tạo các menu đơn giả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.
);
}
}
Bây giờ, ta sẽ request URL
http://localhost:81/drupal/?q=devel/cache/clear
Kết quả như sau :
Hình ảnh
Đây là kỹ thuật rất hữu dụng khi bạn muốn thay đổi cách ứng xử mặc định của drupal mà không chỉnh sửa code bên trong nhân Drupal.
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.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
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.
);
}
}
Bây giờ, ta sẽ request URL
http://localhost:81/drupal/?q=devel/cache/clear
Kết quả như sau :
Hình ảnh
Đây là kỹ thuật rất hữu dụng khi bạn muốn thay đổi cách ứng xử mặc định của drupal mà không chỉnh sửa code bên trong nhân Drupal.
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.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.
);
}
}
Bây giờ, ta sẽ request URL
http://localhost:81/drupal/?q=devel/cache/clear
Kết quả như sau :
Hình ảnh
Đây là kỹ thuật rất hữu dụng khi bạn muốn thay đổi cách ứng xử mặc định của drupal mà không chỉnh sửa code bên trong nhân Drupal.
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.
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 :
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.
);
}
}
Bây giờ, ta sẽ request URL
http://localhost:81/drupal/?q=devel/cache/clear
Kết quả như sau :
Hình ảnh
Đây là kỹ thuật rất hữu dụng khi bạn muốn thay đổi cách ứng xử mặc định của drupal mà không chỉnh sửa code bên trong nhân Drupal.
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 :
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.
Đăng ký:
Bài đăng (Atom)