各位观众老爷,大家好!今天咱们来聊聊 WordPress 权限管理的核心——WP_Roles
类。这玩意儿就像 WordPress 王国里的“户籍管理处”,负责记录每个“公民”(用户角色)的身份信息(权限)。听起来枯燥?别怕,咱用代码和段子,保证让你听得津津有味。
一、 WP_Roles
类的基本结构
首先,让我们看看 WP_Roles
类的真面目(简化版):
<?php
class WP_Roles {
/**
* Array of role objects.
*
* @var array
*/
public $roles = array();
/**
* Array of role names.
*
* @var array
*/
public $role_names = array();
/**
* Option name for storing role list.
*
* @var string
*/
public $role_key;
/**
* Database object.
*
* @var wpdb
*/
public $db;
/**
* Constructor - Registers the role management filters.
*
* The roles option is also updated on each instantiation, in case another
* process updated the role list.
*
* @global wpdb $wpdb WordPress database abstraction object.
*/
public function __construct() {
global $wpdb;
$this->db = $wpdb;
$this->role_key = $this->db->prefix . 'user_roles';
$this->roles = get_option( $this->role_key );
$this->role_names = array();
if ( is_array( $this->roles ) ) {
foreach ( $this->roles as $role => $data ) {
$this->role_names[ $role ] = $data['name'];
}
}
if ( empty( $this->roles ) ) {
$this->roles = array();
$this->role_names = array();
}
// add_filter( 'editable_roles', array( $this, 'editable_roles' ) ); // Removed for brevity
// add_filter( 'map_meta_cap', array( $this, 'map_meta_cap' ), 10, 4 ); // Removed for brevity
}
/**
* Add a new role.
*
* @param string $role User role.
* @param string $display_name Display name of role.
* @param array $capabilities List of capabilities keyed by the capability name.
*/
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->update_roles();
/**
* Fires after a role is added.
*
* @since 2.0.0
*
* @param string $role User role.
*/
do_action( 'add_role', $role );
return $role;
}
/**
* Remove an existing role.
*
* @param string $role Role name.
*/
public function remove_role( $role ) {
if ( ! isset( $this->roles[ $role ] ) ) {
return;
}
unset( $this->roles[ $role ] );
unset( $this->role_names[ $role ] );
$this->update_roles();
/**
* Fires after a role is removed.
*
* @since 2.0.0
*
* @param string $role User role.
*/
do_action( 'remove_role', $role );
}
/**
* Retrieve a role object.
*
* @param string $role Role name.
* @return WP_Role|null WP_Role object if found, null if not.
*/
public function get_role( $role ) {
if ( isset( $this->roles[ $role ] ) ) {
return new WP_Role( $this->roles[ $role ]['capabilities'] );
}
return null;
}
/**
* Retrieve list of role names with display names.
*
* @return array List of role names with display names.
*/
public function get_names() {
return $this->role_names;
}
/**
* Whether the role exists.
*
* @param string $role Role name.
* @return bool
*/
public function is_role( $role ) {
return isset( $this->roles[ $role ] );
}
/**
* Add capability to role.
*
* @param string $role Role name.
* @param string $cap Capability name.
* @param bool $grant Optional, whether to grant or deny capability. Defaults to true.
*/
public function add_cap( $role, $cap, $grant = true ) {
if ( ! isset( $this->roles[ $role ] ) ) {
return;
}
$this->roles[ $role ]['capabilities'][ $cap ] = $grant;
$this->update_roles();
}
/**
* Remove capability from role.
*
* @param string $role Capability name.
* @param string $cap Capability to remove.
*/
public function remove_cap( $role, $cap ) {
if ( ! isset( $this->roles[ $role ] ) ) {
return;
}
unset( $this->roles[ $role ]['capabilities'][ $cap ] );
$this->update_roles();
}
/**
* Update the role list option.
*
* @since 2.0.0
*/
public function update_roles() {
update_option( $this->role_key, $this->roles );
}
}
简单来说,WP_Roles
类主要有以下几个关键成员:
$roles
: 一个数组,存储了所有角色的信息。每个角色都是这个数组的一个元素,以角色名(例如 ‘administrator’, ‘editor’)作为键。每个角色元素的值又是一个数组,包含角色的显示名称(name
)和权限列表(capabilities
)。$role_names
: 一个数组,以角色名作为键,角色显示名称作为值。相当于一个角色名称的“花名册”。$role_key
: 存储角色信息的 WordPress option 的名称。 默认是{$wpdb->prefix}_user_roles
(例如wp_user_roles
)。$db
: WordPress 数据库对象,用于访问数据库。
二、 角色信息的存储方式
WP_Roles
类从 WordPress 的 options
表中读取和存储角色信息。具体来说,它使用 get_option()
和 update_option()
函数来操作名为 $role_key
的 option。 默认是 {$wpdb->prefix}_user_roles
(例如 wp_user_roles
)。
这个 option 的值是一个序列化的 PHP 数组,包含了所有角色的信息。 这种序列化的方式,可以方便地把复杂的数据结构存储到数据库中。
举个栗子:
假设我们有三个角色:’administrator’,’editor’,’subscriber’。存储在 wp_options
表中的 wp_user_roles
option 的值可能如下(简化版):
array(
'administrator' => array(
'name' => 'Administrator',
'capabilities' => array(
'read' => true,
'edit_posts' => true,
'delete_posts' => true,
'manage_options' => true,
),
),
'editor' => array(
'name' => 'Editor',
'capabilities' => array(
'read' => true,
'edit_posts' => true,
'delete_posts' => false,
),
),
'subscriber' => array(
'name' => 'Subscriber',
'capabilities' => array(
'read' => true,
),
),
)
用表格总结一下:
角色名称 (Role Name) | 显示名称 (Display Name) | 权限列表 (Capabilities) |
---|---|---|
administrator | Administrator | read, edit_posts, delete_posts, manage_options, … |
editor | Editor | read, edit_posts, … |
subscriber | Subscriber | read |
三、 WP_Roles
类的主要方法
WP_Roles
类提供了一些关键的方法,用于管理角色和权限。
-
__construct()
(构造函数):- 这个函数在
WP_Roles
类被实例化时调用。 - 它主要负责从数据库中加载角色信息,并将其存储到
$roles
和$role_names
数组中。 - 如果数据库中没有角色信息,它会初始化这两个数组为空。
- 这个函数在
-
add_role( $role, $display_name, $capabilities = array() )
:- 用于添加一个新的角色。
- 参数:
$role
: 角色的名称(例如 ‘author’)。$display_name
: 角色的显示名称(例如 ‘Author’)。$capabilities
: 一个数组,包含了该角色拥有的权限。
- 该方法会将新的角色信息添加到
$roles
和$role_names
数组中,并更新数据库中的wp_user_roles
option。 - 会触发
add_role
action hook。
示例代码:
global $wp_roles; if ( ! isset( $wp_roles ) ) { $wp_roles = new WP_Roles(); } $wp_roles->add_role( 'contributor', 'Contributor', array( 'read' => true, 'edit_posts' => false ) );
这段代码添加了一个名为 ‘contributor’ 的角色,显示名称为 ‘Contributor’,拥有
read
权限,但不能编辑文章。 -
remove_role( $role )
:- 用于删除一个已存在的角色。
- 参数:
$role
: 要删除的角色的名称。
- 该方法会将角色信息从
$roles
和$role_names
数组中移除,并更新数据库中的wp_user_roles
option。 - 会触发
remove_role
action hook。
示例代码:
global $wp_roles; if ( ! isset( $wp_roles ) ) { $wp_roles = new WP_Roles(); } $wp_roles->remove_role( 'contributor' );
这段代码删除了名为 ‘contributor’ 的角色。
-
get_role( $role )
:- 用于获取一个角色的信息。
- 参数:
$role
: 要获取的角色的名称。
- 该方法会返回一个
WP_Role
对象,包含了该角色的权限信息。如果角色不存在,则返回null
。
示例代码:
global $wp_roles; if ( ! isset( $wp_roles ) ) { $wp_roles = new WP_Roles(); } $role = $wp_roles->get_role( 'editor' ); if ( $role ) { echo "Editor 的权限:n"; print_r( $role->capabilities ); } else { echo "角色不存在。n"; }
这段代码获取了 ‘editor’ 角色的信息,并打印了它的权限列表。 这里要注意,返回的是
WP_Role
对象,不是$roles
数组里存的数组。 -
add_cap( $role, $cap, $grant = true )
:- 用于给一个角色添加权限。
- 参数:
$role
: 要添加权限的角色的名称。$cap
: 要添加的权限的名称(例如 ‘edit_others_posts’)。$grant
: 一个布尔值,表示是否授予该权限。默认为true
。
- 该方法会将新的权限添加到
$roles
数组中,并更新数据库中的wp_user_roles
option。
示例代码:
global $wp_roles; if ( ! isset( $wp_roles ) ) { $wp_roles = new WP_Roles(); } $wp_roles->add_cap( 'editor', 'edit_others_posts' );
这段代码给 ‘editor’ 角色添加了 ‘edit_others_posts’ 权限,使其能够编辑其他用户的文章。
-
remove_cap( $role, $cap )
:- 用于从一个角色中移除权限。
- 参数:
$role
: 要移除权限的角色的名称。$cap
: 要移除的权限的名称。
- 该方法会将权限从
$roles
数组中移除,并更新数据库中的wp_user_roles
option。
示例代码:
global $wp_roles; if ( ! isset( $wp_roles ) ) { $wp_roles = new WP_Roles(); } $wp_roles->remove_cap( 'editor', 'edit_others_posts' );
这段代码从 ‘editor’ 角色中移除了 ‘edit_others_posts’ 权限。
-
get_names()
:- 返回一个包含所有角色名称及其显示名称的数组。
-
is_role( $role )
:- 检查一个角色是否存在。
-
update_roles()
:- 将
$roles
数组的内容更新到数据库的wp_user_roles
option 中。这个方法通常在添加、删除角色或修改角色权限后调用。
- 将
四、 WP_Role
类(注意不是 WP_Roles
!)
上面我们提到了 get_role()
方法返回的是一个 WP_Role
对象。 WP_Role
类是 WP_Roles
类的“助手”,它代表一个单独的角色,主要负责管理该角色的权限。
<?php
/**
* Core class used to implement user roles.
*
* @since 2.0.0
*
* @global wpdb $wpdb WordPress database abstraction object.
*/
class WP_Role {
/**
* List of capabilities the role has.
*
* @since 2.0.0
* @var array
*/
public $capabilities;
/**
* Constructor - Set up object properties.
*
* The list of capabilities, `$capabilities`, is passed to the object.
*
* @since 2.0.0
*
* @param array $capabilities List of capabilities keyed by the capability name.
*/
public function __construct( $capabilities = array() ) {
$this->capabilities = $capabilities;
}
/**
* Assign role name.
*
* @since 2.0.0
*
* @param string $role
*/
public function set_name( $role ) {
$this->name = $role;
}
/**
* Check if the role has the given capability.
*
* @since 2.0.0
*
* @param string $cap Capability name.
* @return bool True if the role has the capability, false if not.
*/
public function has_cap( $cap ) {
if ( isset( $this->capabilities[ $cap ] ) ) {
return $this->capabilities[ $cap ];
} else {
return false;
}
}
}
WP_Role
类的主要成员是 $capabilities
数组,它存储了该角色拥有的权限。 has_cap()
方法用于检查角色是否拥有某个权限。
示例代码:
global $wp_roles;
if ( ! isset( $wp_roles ) ) {
$wp_roles = new WP_Roles();
}
$role = $wp_roles->get_role( 'editor' );
if ( $role && $role->has_cap( 'edit_posts' ) ) {
echo "Editor 可以编辑文章。n";
} else {
echo "Editor 不能编辑文章。n";
}
五、 权限映射 (Capability Mapping)
WordPress 的权限系统不仅仅是简单的角色和权限的对应关系。 它还涉及到权限映射,即将一些“虚拟”的权限映射到实际的权限上。
例如,edit_posts
权限可能被映射到 edit_published_posts
和 edit_private_posts
等更细粒度的权限上。 这个映射过程是由 map_meta_cap
filter hook 来实现的。
map_meta_cap
filter hook 允许你根据不同的情况,动态地修改用户所需的权限。 这使得 WordPress 的权限系统更加灵活和强大。
举个例子:
假设你想让某个用户只能编辑自己创建的文章,而不能编辑其他用户的文章。 你可以使用 map_meta_cap
filter hook 来实现这个功能:
function my_map_meta_cap( $caps, $cap, $user_id, $args ) {
if ( 'edit_post' == $cap ) {
$post = get_post( $args[0] );
if ( $post && $user_id != $post->post_author ) {
$caps[] = 'do_not_allow'; // 添加一个不存在的权限,阻止编辑
}
}
return $caps;
}
add_filter( 'map_meta_cap', 'my_map_meta_cap', 10, 4 );
这段代码拦截了 edit_post
权限的检查,如果用户不是文章的作者,就添加一个名为 do_not_allow
的不存在的权限,从而阻止用户编辑该文章。
六、 WP_Roles
类的应用场景
WP_Roles
类在 WordPress 中被广泛使用,主要用于以下几个方面:
- 用户权限管理: 控制用户可以访问哪些后台功能,以及可以执行哪些操作。
- 主题和插件开发: 根据用户的角色,显示不同的内容或提供不同的功能。
- 会员系统: 创建自定义的角色,并根据用户的会员等级,授予不同的权限。
七、 总结
WP_Roles
类是 WordPress 权限管理的核心,它负责存储和管理所有角色和权限的信息。 通过 WP_Roles
类,你可以方便地添加、删除、修改角色和权限,从而实现灵活的用户权限控制。 理解 WP_Roles
类的工作原理,对于开发 WordPress 主题和插件,以及构建复杂的会员系统至关重要。
希望今天的讲座对大家有所帮助。 记住,理解源码是成为 WordPress 大神的必经之路。 下次见!