译者:老葛
回调参数(Callback Arguments)
有时你可能希望为映射到这一路径的函数提供更多的信息。首先,路径的任何额外部分都会被一同传送。让我们把函数改成如下所示:
function mymenu_hello($name = NULL) {
if (!isset($name)) {
$name = t('good looking!');
}
// Sanitize the user submitted name.
return t('Hello @name!', array('@name' => $name));
}
现在如果我们访问页面http://example.com/?q=mymenu,我们将得到:
Hello, good looking!
如果我们访问页面http://example.com/?q=mymenu/Fred,我们得到:
Hello, Fred;
你也可以在菜单钩子内部定义回调参数,通过项数组$items添加可选的键callback arguments。你在这里定义的回调参数将比从路径中生成的参数靠前。这非常有用,因为你可以从不同的菜单项来调用同一个回调函数并为它们提供一些隐藏的上下文信息。
function mymenu_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array(
'title' => t('Greeting'),
'path' => 'mymenu',
'callback' => 'mymenu_hello',
'callback arguments' => array(t('Hi!'), t('Ho!')),
'access' => TRUE
);
}
return $items;
}
function mymenu_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('good looking');
}
return t('Hello @name!', array('@name' => $name));
}
现在访问页面http://example.com/?q=mymenu/Fred,我们得到如图4-5所示的结果。
图4-5 传递并展示回调参数
在回调参数的对应数组中,键将被忽略,所以你不能使用键来映射函数参数;只有顺序才是重要的。回调参数通常是变量,并且经常用在动态菜单项中(比如当$may_cache为FALSE时添加他们)。
菜单嵌套:
到目前为止我们仅定义了一个单独的静态菜单项。让我们添加第2个:
/**
* Implementation of hook_menu().
*/
function mymenu_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array(
'title' => t('Greeting'),
'path' => 'mymenu',
'callback' => 'mymenu_hello',
'access' => TRUE
);
$items[] = array(
'title' => t('Farewell'),
'path' => 'mymenu/goodbye',
'callback' => 'mymenu_goodbye',
'access' => TRUE
);
}
return $items;
}
Drupal将发现第2个菜单项(mymenu/goodbye)的路径是第一个菜单项路径(mymenu)的孩子。因此,当渲染菜单时(转化为HTML格式),Drupal将对第2个菜单进行缩进,如图4-6所示。
当然,一个主题(theme)可以渲染设计者希望的任何菜单样式。
图4-6 嵌套菜单(Nested menu)
访问控制
到目前为止,在我们的例子中,我们简单的把菜单项的键access设置为TRUE,这意味着任何用户都可以访问我们的菜单。通常菜单访问是通过在模块内部使用hook_perm()定义权限来控制的,通过使用user_access()来测试这些权限。让我们定义一个名为”receive greeting”的权限,如果一个用户没拥有一个获取这一权限的角色,如果他(或她)想访问页面http://example.com/?q=mymenu 时,他将收到一个“拒绝访问”信息。
/**
* Implementation of hook_perm().
*/
function mymenu_perm() {
return array('receive greeting');
}
/**
* Implementation of hook_menu().
*/
function mymenu_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array(
'title' => t('Greeting'),
'path' => 'mymenu',
'callback' => 'mymenu_hello',
'access' => user_access('receive greeting') // Returns TRUE or FALSE.
);
}
return $items;
}
这样,菜单系统可被看作是个守门员,他根据用户的角色来决定那些路径可以访问,那些将被拒绝访问。
菜单项可以嵌套。举例来说,一个路径为foo/bar的菜单项是路径为foo的菜单项的孩子。当决定对一个菜单项的访问时,Drupal将查找菜单项的全路径对应的键access并使用它。如果键access为True,访问将被允许,即便它的父菜单的键access是FALSE。如果没有为一个菜单项设置access,将会默认使用它父菜单的键access。如果父菜单也没有设置access,Drupal将依次向上迭代直到找到一个access键(菜单树的根的键access为TRUE)。本地任务为简单的嵌套菜单项。表4-1展示了基于一个菜单项的访问设置和它父菜单的访问控制来决定一个用户的访问被允许还是被拒绝。
表4-1 访问设置和用户访问结果
Parent Child User Access
FALSE FALSE Denied
TRUE FALSE Denied
FALSE TRUE Allowed
TRUE TRUE Allowed
FALSE Undefined Denied
TRUE Undefined Allowed
各种菜单项
当你在菜单钩子中添加一个菜单项时,一个你可能用到的键就是类型(type)。如果你们有定义类型,将会使用默认类型MENU_NORMAL_ITEM。Drupal将根据你分配的类型的不同来区别对待相应的菜单。每一个菜单项类型都有一系列的标记或者属性组成。表4-2列出了菜单项类型的标记。
表4-2菜单项类型标记
Binary Hexadecimal Decimal Constant
000000000001 0x0001 1 MENU_IS_ROOT
000000000010 0x0002 2 MENU_VISIBLE_IN_TREE
000000000100 0x0004 4 MENU_VISIBLE_IN_BREADCRUMB
000000001000 0x0008 8 MENU_VISIBLE_IF_HAS_CHILDREN
000000010000 0x0010 16 MENU_MODIFIABLE_BY_ADMIN
000000100000 0x0020 32 MENU_MODIFIED_BY_ADMIN
000001000000 0x0040 64 MENU_CREATED_BY_ADMIN
000010000000 0x0080 128 MENU_IS_LOCAL_TASK
000100000000 0x0100 256 MENU_EXPANDED
001000000000 0x0200 512 MENU_LINKS_TO_PARENT
举例来说,常量MENU_NORMAL_ITEM拥有标记MENU_VISIBLE_IN_TREE,MENU_VISIBLE_IN_BREADCRUMB,和 MENU_MODIFIABLE_BY_ADMIN,如表4-3所示。看一下不同的标记在同一个单独的常量中是如何表示的。
表4-3 菜单项类型MENU_NORMAL_ITEM的标记
Binary Constant
000000000010 MENU_VISIBLE_IN_TREE
000000000100 MENU_VISIBLE_IN_BREADCRUMB
000000010000 MENU_MODIFIABLE_BY_ADMIN
---------------------------------------------------------------
000000010110 MENU_NORMAL_ITEM
因此MENU_NORMAL_ITEM拥有下列标记000000010110,MENU_NORMAL_ITEM
表4-4展示了可用的菜单项类型和他们所表达的标记
表4-4菜单项类型所表达的标记
当你定义你的菜单项类型时,你应该使用那一个常量呢?查看表4-4,看一下你想使用那些标记,然后使用包含这些标记的常量。对于每一个常量的详细描述,参看includes/menu里面的注释。最常用的为MENU_CALLBACK, MENU_LOCAL_TASK, 和 MENU_DEFAULT_LOCAL_TASK。仔细阅读可获更详细信息。