各位观众老爷,晚上好!我是今天的讲师,咱们今天就来聊聊 WordPress 权限管理的核心——WP_Roles
类,以及它背后的 $wp_roles
全局变量。
准备好了吗?Let’s dive in!
开场白:权限这玩意儿,真要命!
在 Web 开发的世界里,权限管理绝对是个绕不开的坎儿。想想看,你辛辛苦苦搭建的网站,总不能让阿猫阿狗都能随便改吧?谁能发文章?谁能删评论?谁能安装插件?这些都得管起来!
WordPress 作为一个强大的 CMS,自然也有一套完整的权限管理机制。而 WP_Roles
类,就是这套机制的核心大脑,它负责掌管所有的用户角色和权限信息。
WP_Roles
类:角色与权限的总指挥
WP_Roles
类,顾名思义,就是用来管理用户角色的。它定义了各种角色(比如管理员、编辑、作者、投稿者、订阅者),以及每个角色拥有的权限。
我们先来大概看看这个类的主要属性和方法,心里有个数:
-
属性:
$roles
: 一个数组,存储了所有角色的信息。每个角色都是一个数组,包含角色名、显示名和拥有的权限。$role_names
: 一个数组,存储了所有角色的显示名。$role_objects
: 一个数组,存储了所有WP_Role
对象,每个对象代表一个角色。
-
主要方法:
__construct()
: 构造函数,负责初始化角色信息。add_role()
: 添加一个新的角色。remove_role()
: 删除一个角色。get_role()
: 获取一个WP_Role
对象。get_names()
: 获取所有角色的显示名。get_roles()
: 获取所有角色的信息。is_role()
: 检查一个角色是否存在。role_exists()
: 检查一个角色是否存在(别名)。add_cap()
: 给角色添加一个权限。remove_cap()
: 从角色移除一个权限。get_cap()
: 检查角色是否拥有某个权限。
是不是觉得有点眼花缭乱?别怕,我们一点点拆解。
$wp_roles
全局变量:单例模式的妙用
重点来了!WP_Roles
类并不是直接使用的,而是通过一个全局变量 $wp_roles
来实现单例模式。
什么是单例模式?简单来说,就是确保一个类只能被实例化一次。这样可以避免重复创建对象,浪费资源,而且方便全局访问。
在 WordPress 中,$wp_roles
全局变量就是用来存储 WP_Roles
类的唯一实例的。
让我们看看 WordPress 是如何实现这一点的:
// wp-includes/capabilities.php
global $wp_roles;
if ( ! isset( $wp_roles ) ) {
$wp_roles = new WP_Roles();
}
这段代码简洁明了:
- 首先,声明一个全局变量
$wp_roles
。 - 然后,检查
$wp_roles
是否已经被设置。 - 如果
$wp_roles
还没有被设置,就创建一个WP_Roles
类的实例,并赋值给$wp_roles
。
这样,无论你在 WordPress 的哪个地方使用 $wp_roles
,访问的都是同一个 WP_Roles
类的实例。
WP_Roles
类的构造函数:初始化角色信息
当我们创建一个 WP_Roles
类的实例时,构造函数 __construct()
会被自动调用。这个函数的主要任务是从数据库中加载角色和权限信息。
// wp-includes/class-wp-roles.php
public function __construct() {
global $wpdb;
$this->roles = get_option( 'wp_user_roles' );
if ( empty( $this->roles ) ) {
/**
* Fires after the default roles are created.
*
* @since 3.0.0
*/
do_action( 'default_roles' );
update_option( 'wp_user_roles', $this->roles );
}
$this->role_names = get_option( 'wp_user_roles', array() );
if ( empty( $this->role_names ) ) {
$this->role_names = array();
}
$this->role_objects = array();
if ( is_array( $this->roles ) ) {
foreach ( array_keys( $this->roles ) as $role ) {
$this->role_objects[ $role ] = new WP_Role( $role, $this->roles[ $role ] );
}
}
}
我们来解读一下这段代码:
- 首先,获取全局数据库对象
$wpdb
。 - 然后,尝试从
wp_options
表中获取wp_user_roles
选项的值,并赋值给$this->roles
。这个选项存储了所有角色的信息。 - 如果
$this->roles
为空,说明还没有任何角色信息,那么就触发default_roles
action。这个 action 允许插件或主题添加默认的角色。 - 接着,将
$this->roles
更新到wp_options
表中。 - 然后,从
wp_options
表中获取wp_user_roles
选项的值,并赋值给$this->role_names
。 - 最后,遍历
$this->roles
数组,为每个角色创建一个WP_Role
对象,并存储到$this->role_objects
数组中。
WP_Role
类:角色的具体实现
注意到了吗?在 WP_Roles
类的构造函数中,我们创建了 WP_Role
类的对象。WP_Role
类代表一个具体的角色,它封装了角色的名称、显示名和权限信息。
// wp-includes/class-wp-role.php
class WP_Role {
public $name;
public $capabilities;
public function __construct( $role, $capabilities ) {
$this->name = $role;
$this->capabilities = $capabilities;
}
public function add_cap( $cap, $grant = true ) {
$this->capabilities[ $cap ] = $grant;
return update_option( 'wp_user_roles', get_option( 'wp_user_roles' ) );
}
public function remove_cap( $cap ) {
unset( $this->capabilities[ $cap ] );
return update_option( 'wp_user_roles', get_option( 'wp_user_roles' ) );
}
public function has_cap( $cap ) {
if ( isset( $this->capabilities[ $cap ] ) ) {
return $this->capabilities[ $cap ];
}
return false;
}
}
这个类非常简单:
$name
: 角色的名称。$capabilities
: 一个数组,存储了角色拥有的权限。add_cap()
: 给角色添加一个权限。remove_cap()
: 从角色移除一个权限。has_cap()
: 检查角色是否拥有某个权限。
常用方法解析:增删改查,样样精通
现在,我们来详细看看 WP_Roles
类的一些常用方法,了解它们是如何操作角色和权限的。
-
add_role()
:添加角色这个方法用于添加一个新的角色。
// wp-includes/class-wp-roles.php public function add_role( $role, $display_name, $capabilities = array() ) { if ( isset( $this->roles[ $role ] ) ) { return; } $this->roles[ $role ] = array( 'name' => $display_name, 'capabilities' => $capabilities ); $this->role_names[ $role ] = $display_name; $this->role_objects[ $role ] = new WP_Role( $role, $capabilities ); update_option( 'wp_user_roles', $this->roles ); /** * Fires after a role is added. * * @since 4.3.0 * * @param string $role Role name. * @param string $display_name Role display name. * @param array $capabilities List of role capabilities. */ do_action( 'add_role', $role, $display_name, $capabilities ); return $role; }
这个方法做了以下几件事:
- 检查角色是否已经存在,如果存在则直接返回。
- 将角色信息添加到
$this->roles
数组中。 - 将角色的显示名添加到
$this->role_names
数组中。 - 创建一个
WP_Role
对象,并添加到$this->role_objects
数组中。 - 将
$this->roles
更新到wp_options
表中。 - 触发
add_role
action。
使用示例:
global $wp_roles; $wp_roles->add_role( 'customer', 'Customer', array( 'read' => true, 'edit_posts' => false ) );
这段代码添加了一个名为 "customer" 的角色,显示名为 "Customer",拥有
read
权限,但没有edit_posts
权限。 -
remove_role()
:删除角色这个方法用于删除一个角色。
// wp-includes/class-wp-roles.php public function remove_role( $role ) { if ( ! isset( $this->roles[ $role ] ) ) { return; } unset( $this->roles[ $role ] ); unset( $this->role_names[ $role ] ); unset( $this->role_objects[ $role ] ); update_option( 'wp_user_roles', $this->roles ); /** * Fires after a role is removed. * * @since 4.3.0 * * @param string $role Role name. */ do_action( 'remove_role', $role ); }
这个方法做了以下几件事:
- 检查角色是否存在,如果不存在则直接返回。
- 从
$this->roles
数组中删除角色信息。 - 从
$this->role_names
数组中删除角色的显示名。 - 从
$this->role_objects
数组中删除WP_Role
对象。 - 将
$this->roles
更新到wp_options
表中。 - 触发
remove_role
action。
使用示例:
global $wp_roles; $wp_roles->remove_role( 'customer' );
这段代码删除了名为 "customer" 的角色。
-
get_role()
:获取角色对象这个方法用于获取一个
WP_Role
对象。// wp-includes/class-wp-roles.php public function get_role( $role ) { if ( isset( $this->role_objects[ $role ] ) ) { return $this->role_objects[ $role ]; } return null; }
这个方法很简单,就是从
$this->role_objects
数组中查找对应的WP_Role
对象,如果找到则返回,否则返回null
。使用示例:
global $wp_roles; $customer_role = $wp_roles->get_role( 'customer' ); if ( $customer_role ) { // Do something with the customer role echo "Customer role exists!"; } else { echo "Customer role does not exist."; }
-
add_cap()
:添加权限这个方法用于给角色添加一个权限。
// wp-includes/class-wp-roles.php public function add_cap( $role, $cap, $grant = true ) { if ( ! isset( $this->roles[ $role ] ) ) { return; } $this->roles[ $role ]['capabilities'][ $cap ] = $grant; $this->role_objects[ $role ]->add_cap( $cap, $grant ); update_option( 'wp_user_roles', $this->roles ); }
这个方法做了以下几件事:
- 检查角色是否存在,如果不存在则直接返回。
- 将权限添加到
$this->roles
数组中对应角色的capabilities
数组中。 - 调用
WP_Role
对象的add_cap()
方法,更新角色对象的权限信息。 - 将
$this->roles
更新到wp_options
表中。
使用示例:
global $wp_roles; $wp_roles->add_cap( 'customer', 'purchase_products' );
这段代码给名为 "customer" 的角色添加了
purchase_products
权限。 -
remove_cap()
:移除权限这个方法用于从角色移除一个权限。
// wp-includes/class-wp-roles.php public function remove_cap( $role, $cap ) { if ( ! isset( $this->roles[ $role ] ) ) { return; } unset( $this->roles[ $role ]['capabilities'][ $cap ] ); $this->role_objects[ $role ]->remove_cap( $cap ); update_option( 'wp_user_roles', $this->roles ); }
这个方法做了以下几件事:
- 检查角色是否存在,如果不存在则直接返回。
- 从
$this->roles
数组中对应角色的capabilities
数组中删除权限。 - 调用
WP_Role
对象的remove_cap()
方法,更新角色对象的权限信息。 - 将
$this->roles
更新到wp_options
表中。
使用示例:
global $wp_roles; $wp_roles->remove_cap( 'customer', 'purchase_products' );
这段代码从名为 "customer" 的角色移除了
purchase_products
权限。
权限的存储方式:wp_options
表的秘密
现在,我们来揭秘一下角色和权限信息是如何存储在数据库中的。
WP_Roles
类会将角色和权限信息存储在 wp_options
表中的 wp_user_roles
选项中。这个选项的值是一个序列化的 PHP 数组。
我们可以通过以下代码来查看这个选项的值:
global $wpdb;
$roles = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'wp_user_roles'" );
$roles = maybe_unserialize( $roles );
echo '<pre>';
print_r( $roles );
echo '</pre>';
这段代码会从数据库中获取 wp_user_roles
选项的值,反序列化后打印出来。你就可以看到角色和权限信息的具体结构了。
map_meta_cap()
:权限映射的桥梁
WordPress 的权限系统不仅仅是简单的角色和权限的对应关系,还涉及到权限映射。
比如,edit_post
权限并不是直接授予给用户的,而是通过 map_meta_cap()
函数将 edit_post
权限映射到更具体的权限上,比如 edit_others_posts
或 edit_published_posts
。
map_meta_cap()
函数会根据具体的上下文(比如用户 ID、文章 ID)来判断用户是否真的拥有编辑这篇文章的权限。
这个函数是 WordPress 权限系统的一个重要组成部分,它使得权限管理更加灵活和安全。
案例分析:自定义角色和权限
最后,我们来看一个实际的案例,演示如何自定义角色和权限。
假设我们要创建一个名为 "contributor_plus" 的角色,这个角色拥有投稿者的所有权限,并且可以编辑自己的文章。
首先,我们需要添加这个角色:
add_action( 'init', 'add_contributor_plus_role' );
function add_contributor_plus_role() {
global $wp_roles;
if ( ! isset( $wp_roles ) ) {
return;
}
if ( get_role( 'contributor_plus' ) ) {
return;
}
$contributor = get_role( 'contributor' );
if ( ! $contributor ) {
return;
}
$caps = $contributor->capabilities;
$caps['edit_posts'] = true;
$caps['edit_published_posts'] = true;
add_role( 'contributor_plus', 'Contributor Plus', $caps );
}
这段代码在 init
action 中添加了一个名为 "contributor_plus" 的角色,并赋予了 edit_posts
和 edit_published_posts
权限。
总结:权限管理的奥秘
今天,我们深入探讨了 WordPress 权限管理的核心——WP_Roles
类和 $wp_roles
全局变量。
我们了解了:
WP_Roles
类是用来管理用户角色的。$wp_roles
全局变量实现了单例模式,确保只有一个WP_Roles
类的实例。WP_Role
类代表一个具体的角色,封装了角色的名称、显示名和权限信息。WP_Roles
类提供了添加、删除、修改角色和权限的方法。- 角色和权限信息存储在
wp_options
表中的wp_user_roles
选项中。 map_meta_cap()
函数实现了权限映射,使得权限管理更加灵活和安全。
通过理解这些概念,你可以更好地掌握 WordPress 的权限管理机制,自定义角色和权限,满足你的实际需求。
希望今天的讲座对你有所帮助!下次再见!