WordPress 角色(Role)与权限(capability)简介

0

WP 会员权限机制的发展

WordPress早期在1.5版时开始使用的权限设计是采用User Level机制,也就是将内置的全部权限切分为十个等级,而每个等级能做的事都定义出来,所以使用者可以透过读取user的等级来决定权限。

这样充满限制的权限设计,可想而知不会太长命,果然到了WP2.0开始就建议大家换用角色(Roles)与能力(Capabilities)机制了,并且到了WP3.0,User Level就成为了不建议使用(deprecated)的功能了。

WP 自定义角色(Roles)与能力(Capabilities)

简单来说,Roles与Capabilities的机制就是每个角色能拥有许多不同的能力,除了内置的六个角色(超级管理者-Super Admin, 管理者-Administrator, 编辑-Editor, 作者-Author, 投稿者-Contributor, 订阅者-Subscriber),开发人员也能自定义新的角色,而能力也是如此,除了内置的能力(读文章、发表文章、管理使用者…等等),也能自定义新的能力。自定义新角色时也能顺便指定新的自定义能力,方式是:

add_role('test_role','测试者',array('test_cap'));

你可以把这个语法写在自定义的plugin里,当然也能用在主题(theme)的function.php中。其中test_role是我自定义的新角色,「测试者」是新角色显示的名称,而test_cap则是此角色拥有的能力,执行了这行,就代表你的WP出现了一个新的角色-test_role,而这个角色拥有test_cap这项能力。

为什么你会觉得WP的会员权限很鸡肋?

我知道WordPress的会员权限设定常常饱受批评,就拿Drupal的权限设定来说,预设的后台设置就非常完整的提供了各项读取的权限设定,WP一比较之下,感觉就弱掉了。不过我个人认为,WP也能办到一样的事,只是通常在开发Plugin时,开发者没有把权限设定的code完整的实作出来。

因为在我们定义好新的角色或新的能力之后,我们必须在自定义的主题或plugin中加上判断,透过取得目前User的所属角色及拥有的能力,再来决定对不同权限作不同的呈现或动作。我想WP预设的会员权限这么弱,大概因为毕竟WP的大户是博客,会员通常只有博主一人,所以权限部份时常没被定义到也很正常XD。

实现有问题!?

好的,就在实现自定义角色及自定义能力时,问题发生了。有个内置的function叫current_user_can(),wp的官方文件说,我们可以透过它来判断目前的使用者是否为某特定的角色,或者是否拥有特定的能力,因此它的参数可以是「角色」也可以是「能力」,但是我测试的结果是,给它自定义的「角色」去做判断,运作是正常的;但给它自定义的「能力」进行判断,运作就不正常了。

在Google了几个小时,以及骂了好几声脏话之后,我决定去看原始代码。这些跟权限相关的functions定义在wp-includes/capabilities.php 里,从current_user_can()出发,可以发现它又呼叫了has_cap这个function,去取得目前使用者的所有能力,事情就错在这里。

在它把目前使用者所有的能力都放进$capabilities这个数组后,我自定义的能力它找不到,自定义的角色却找得到,於是print_r这个阵列后发现它长这样:

Array ( [0] => test_cap [test_role] => 1 )

白话一点说,它里面有两个值。我们可以用$capabilities[0] 去取得 test_cap 这个值,也可以用 $capabilities[‘test_role’]去取得1这个值,偏偏在has_cap里面,它统一用 $capabilities[‘角色或能力名’] 这种方式来判断是否拥有某能力,当然 current_user_can 也一并被影响了,所以当我们用 current_user_can(‘test_cap’)时,它只会回传false,而current_user_can(‘test_role’)才会正确的取得1,并且被判定为True,真是XX你个OO。

解决方案

简单的解决方式就是用它正常的部份,也就是用角色来判断就好:

if (current_user_can("test_role"))
{
    echo 'yes, he is the right role!';
}

缺点是很鸡肋、不正常、不合理,照理说能力是可以跨角色的,只拿角色判断,完全不弹性,不过在plugin设计不复杂的情况下是可行的。那如果我们现阶段真的很想用能力来做判断怎么办? 那你可以这样做:

// 先取得目前的使用者所属的角色
$current_user = wp_get_current_user();
$user_roles = $current_user->roles;
 
// 取得使用者所属角色后,再检查这个角色拥有的能力
$role = get_role($user_roles[0]);
foreach ($role->capabilities as $hiscap)
{
    // 如果这个角色拥有 test_cap 这个自定义能力
    if ($hiscap == 'test_cap')
    {
        echo '是的,现在的使用者有test_cap这项能力';
        break;
    }
}

发表评论

您的邮箱不会公开,当您的评论有新的回复时,会通过您填写的邮箱向您发送评论内容。 必填字段 *

为何看不到我发布的评论?

正在提交, 请稍候...