整个例子看起来很糟糕而且很糟糕。简而言之,一个笑话。首先,让我回答你的问题,然后我会继续解释为什么你不应该在实践中遵循这个例子。
来自includes/menu.inc:
if (!isset($item['access callback']) && isset($item['access arguments'])) {
// Default callback.
$item['access callback'] = 'user_access';
}
当您不再需要访问回调时取消设置访问回调(毕竟现在依赖于布尔值)可以防止 Drupal 路由系统中过于聪明的逻辑在 user_access() 中被拍打,所以它有事可做。
现在,谈谈为什么这是糟糕的代码。
hook_menu() 和 hook_menu_alter() 都在缓存清除时运行(更具体地说,在重建菜单路由系统时)。这意味着无论哪个用户访问该站点以重建菜单的权限都将被硬编码到菜单路由行为中。这是一个非常糟糕和不一致的安排。
如果您想根据权限阻止对路径的访问,您需要将回调更改为可以测试该权限的内容。然后当菜单重建时,它会检查每次页面加载的新回调函数,看看当前用户是否应该被授予权限。
一个简单的例子可能如下所示:
/**
* Implementation of hook_menu_alter().
*/
function joke_menu_alter(&$items) {
$items['node/add/joke']['access callback'] = 'user_access';
$items['node/add/joke']['access arguments'] = array('administer nodes');
}
现在我们有一个函数,它采用节点/添加/笑话路径并声明唯一重要的是用户是否具有administer nodes 权限。当然,这比示例的明显意图更受限制,即保留现有的访问控制,但还要求用户拥有administer nodes 权限。
这也是可以修复的,但更复杂。借用Spaces项目的一些概念:
/**
* Implementation of hook_menu_alter().
*/
function joke_menu_alter(&$items) {
$path = 'node/add/joke';
$items[$path]['access arguments'][] = $items[$path]['access callback'];
$items[$path]['access callback'] = 'joke_menu_access';
}
function joke_menu_access() {
$args = func_get_args();
$access_callback = array_pop($args);
$original_access = call_user_func_array($access_callback, $args);
return $original_access && user_access('administer nodes');
}
我们已经成功地将原始访问回调封装在一个新的访问回调中,我们可以在其中添加任何我们需要的额外逻辑。
请注意,在最后两个函数示例中,我使用了$path 变量来保持代码简单。我还将$original_access 分隔到它自己的行中并首先对其进行检查,实际上我会先检查user_access(),因为它几乎肯定会比原始访问回调中发生的任何事情都具有更高的性能。