wordpress 功能
User management on WordPress is based on roles and capabilities.
WordPress上的用户管理基于角色和功能。
A role is an entity made of a unique name and a set of capabilities. Each capability is used to define if the role has access to a particular feature of the platform.
角色是由唯一名称和一组功能组成的实体。 每个功能都用于定义角色是否有权访问平台的特定功能。
Let’s take a closer look at how WordPress Roles and Capabilities work.
让我们仔细看看WordPress角色和功能的工作方式。
引擎盖下 (Under the Hood)
存储角色 (Storing the Roles)
The list of default roles and capabilities is available on the WordPress Codex.
默认角色和功能的列表在WordPress Codex上可用。
The database stores this list in the wp_options
table.
数据库将此列表存储在wp_options
表中。
It uses the serialized wp_user_roles
key.
它使用序列化的wp_user_roles
密钥。
The unserialized data looks like this:
未序列化的数据如下所示:
array(
'administrator' => array(
'name' => 'Administrator',
'capabilities' => array(
'switch_themes' => true,
'edit_themes' => true,
'activate_plugins' => true,
'edit_plugins' => true,
'edit_users' => true,
// [...]
)
),
'contributor' => array(
'name' => 'Contributor',
'capabilities' => array(
'delete_pages' => true,
'delete_others_pages' => true,
'delete_published_pages' => true,
'delete_posts' => true,
// [...]
)
),
// [...]
);
This meta is automatically set when installing a new WordPress site.
安装新的WordPress网站时会自动设置此meta。
When WordPress starts, the WP_Roles
class loads the list from the database.
当WordPress启动时, WP_Roles
类从数据库加载列表。
This occurs between the plugins_loaded
and the init
hooks.
这发生在plugins_loaded
和init
挂钩之间。
将用户链接到角色 (Linking Users to Roles)
WordPress uses a meta_key
, stored in the wp_usermeta
table, to link a user to his role.
WordPress的使用meta_key
,存储在wp_usermeta
表,用户链接到他的角色。
Once unserialized, the meta looks like this:
一旦取消序列化,元数据将如下所示:
array(
'administrator' => true
)
Note that WordPress uses an array, although a user can only have one role at a time, we will see later why.
请注意,WordPress使用数组,尽管一个用户一次只能拥有一个角色,但稍后我们将了解原因。
Also, keep in mind that the wp_
part of the meta key is the prefix of the current blog.
另外,请记住,元密钥的wp_
部分是当前博客的前缀。
(We can get it by using the $GLOBALS['wpdb']->get_blog_prefix()
function).
(我们可以使用$GLOBALS['wpdb']->get_blog_prefix()
函数获得它)。
On a multisite installation, this would allow a user to use different roles on different instances:
在多站点安装中,这将允许用户在不同的实例上使用不同的角色:
wp_capabilities => a:1:{s:13:"administrator";b:1;}
wp_capabilities => a:1:{s:13:"administrator";b:1;}
wp_10_capabilities => a:1:{s:11:"contributor";b:1;}
wp_10_capabilities => a:1:{s:11:"contributor";b:1;}
wp_15_capabilities => a:1:{s:10:"subscriber";b:1;}
wp_15_capabilities => a:1:{s:10:"subscriber";b:1;}
[...]
[...]
This rule also applies to the wp_user_roles
entry that we have seen before, in the wp_options
table.
该规则也适用于我们之前在wp_options
表中看到的wp_user_roles
条目。
Finally, we can see the wp_user_level
meta along with the role.
最后,我们可以看到wp_user_level
元数据以及该角色。
It was used to handle roles in old WordPress versions, and is now deprecated.
它曾经用于处理旧WordPress版本中的角色,现在已弃用 。
在核心中使用功能 (Working with Capabilities in the Core)
We have seen how roles are loaded and linked to users; from there, WordPress is able to get the capabilities of a given user, when needed.
我们已经看到了角色是如何加载并链接到用户的。 从那里,WordPress可以在需要时获得给定用户的功能。
Several default capabilities are hard-coded in the WordPress core.
几个默认功能在WordPress核心中进行了硬编码。
For instance, when loading the plugin screen, it will check if the current user can manage plugins, by running the following code:
例如,在加载插件屏幕时,它将通过运行以下代码来检查当前用户是否可以管理插件:
if (!current_user_can('activate_plugins'))
{
wp_die(__('You do not have sufficient permissions to manage plugins for this site.'));
}
Roles are never hard-coded; a role is only a capabilities wrapper, it only exists in the database.
角色从不硬编码; 角色只是功能包装,它仅存在于数据库中。
使用角色和功能:WordPress API (Working with Roles & Capabilities: the WordPress API)
访问API (Access the API)
WordPress provides the following global functions to help us work with roles.
WordPress提供以下全局功能来帮助我们处理角色。
current_user_can() (current_user_can())
Checks if the current user owns the required capability.
检查当前用户是否拥有所需的功能。
add_action('init', function()
{
if (current_user_can('install_plugins'))
{
echo 'you can install plugins';
}
else
{
echo 'You cannot install plugins';
}
});
WP_User :: has_cap (WP_User::has_cap)
Checks if a specific user owns a capability.
检查特定用户是否拥有功能。
add_action('init', function()
{
$user = get_user_by('slug', 'admin');
if ($user->has_cap('install_plugins'))
{
echo 'Admin can install plugins';
}
else
{
echo 'Admin cannot install plugins';
}
});
We can note that current_user_can
uses this function.
我们可以注意到current_user_can
使用此功能。
get_editable_roles() (get_editable_roles())
Returns available roles.
返回可用角色。
add_action('admin_init', function()
{
$roles = get_editable_roles();
var_dump($roles);
});
The list may be overriden with the editable_roles
filter, so we should not rely on this function to get the complete roles list on a website.
该列表可以用editable_roles
过滤器覆盖,因此我们不应该依赖此功能来获取网站上完整的角色列表。
Note the usage of the admin_init
hook, as the function is not loaded yet on the init
one.
请注意admin_init
钩子的用法,因为该函数尚未加载到init
钩子上。
get_role() (get_role())
Gets a WP_Role
object from its slug.
WP_Role
对象获取WP_Role
对象。
add_action('init', function()
{
$role = get_role('administrator');
var_dump($role);
});
// This will print:
// WP_Role Object
// (
// [name] => administrator
// [capabilities] => Array
// (
// [switch_themes] => 1
// [edit_themes] => 1
// [activate_plugins] => 1
// [edit_plugins] => 1
// [...]
WP_Role :: has_cap() (WP_Role::has_cap())
Checks if a role has the required capability.
检查角色是否具有所需的功能。
add_action('init', function()
{
$role = get_role('administrator');
var_dump($role->has_cap('install_plugins')); // Prints TRUE
});
自定义API (Customizing the API)
WordPress also offers a complete API to customize the roles and their capabilities.
WordPress还提供了完整的API以自定义角色及其功能。
add_role() (add_role())
Registers a new role in the database.
在数据库中注册一个新角色。
add_action('init', function()
{
add_role('plugins_manager', 'Plugins Manager', array(
'install_plugins',
'activate_plugins',
'edit_plugins'
));
});
remove_role() (remove_role())
Removes the required role from the database, if it exists.
从数据库中删除所需的角色(如果存在)。
add_action('init', function()
{
remove_role('plugins_manager');
});
WP_Role :: add_cap() (WP_Role::add_cap())
Adds a capability to a role.
向角色添加功能。
add_action('init', function()
{
$role = get_role('contributor');
$role->add_cap('install_plugins');
});
This may be a core capability (install_plugins
, edit_posts
, …) or any custom string (my_awesome_plugin_cap
).
这可能是一项核心功能( install_plugins
, edit_posts
…)或任何自定义字符串( my_awesome_plugin_cap
)。
It allows us to register as many custom capabilities as we need for our plugins.
它允许我们注册我们插件所需的许多自定义功能。
WP_Role :: remove_cap() (WP_Role::remove_cap())
Removes a capability from a role, if it exists.
从角色中删除功能(如果存在)。
add_action('init', function()
{
$role = get_role('contributor');
$role->remove_cap('install_plugins');
});
WP_User :: add_role() (WP_User::add_role())
Adds a role to the given user.
向给定用户添加角色。
add_action('init', function()
{
$user = get_user_by('slug', 'admin');
$user->add_role('contributor');
});
This function allows you to theoretically set many roles on the same user.
从理论上讲,此功能使您可以在同一用户上设置许多角色。
As the WordPress backend only displays and manages one role per user, we should not add several roles for a user, and always use WP_User::remove_role()
before adding a new one.
由于WordPress后端仅显示和管理每个用户一个角色,因此我们不应该为一个用户添加多个角色,并且在添加新角色之前始终使用WP_User::remove_role()
。
WP_User :: remove_role() (WP_User::remove_role())
Removes a role from the given user.
从给定用户中删除角色。
add_action('init', function()
{
$user = get_user_by('slug', 'admin');
$user->remove_role('administrator');
});
WP_User :: add_cap() (WP_User::add_cap())
Adds a capability to the given user.
向给定的用户添加功能。
add_action('init', function()
{
$user = get_user_by('slug', 'admin');
$user->add_cap('my_custom_cap');
});
This can be useful if we want to add a single capability to a user, without having to create a complete role.
如果我们要向用户添加单个功能,而不必创建完整的角色,则这很有用。
WP_User :: remove_cap() (WP_User::remove_cap())
Removes a capability from the given user.
从给定的用户删除功能。
add_action('init', function()
{
$user = get_user_by('slug', 'admin');
$user->remove_cap('my_custom_cap');
});
WordPress API的几个问题 (A Few Issues with the WordPress API)
Everything looks fine with the functions we have seen, except one thing: database access and performance.
除了一件事:数据库访问和性能外,一切与我们看到的功能都很好。
The main concern we have when working with roles and capabilities is when should we trigger our code?
使用角色和功能时 ,我们主要关心的是何时应该触发代码?
To explain this, let’s have a look at the code of the WordPress core.
为了解释这一点,让我们看一下WordPress核心的代码。
First, we want to add a new, empty role:
首先,我们要添加一个新的空角色:
add_action('init', function()
{
add_role('plugins_manager', 'Plugins Manager', array());
});
Here are the first lines of the add_role
function (which actually redirects to WP_Roles::add_role
):
这是add_role
函数的第一行(实际上重定向到WP_Roles::add_role
):
public function add_role( $role, $display_name, $capabilities = array() ) {
if ( isset( $this->roles[$role] ) )
return;
If we add a new role, the add_role
function runs once, and then does nothing.
如果添加新角色,则add_role
函数运行一次,然后什么也不做。
Next, let’s say we want to add a capability to our freshly created role:
接下来,假设我们要为新创建的角色添加功能:
add_action('init', function()
{
$role = get_role('plugins_manager');
$role->add_cap('install_plugins');
});
The WP_Role::add_cap()
function in WordPress 4.2.2 looks like this:
WordPress 4.2.2中的WP_Role::add_cap()
函数如下所示:
public function add_cap( $role, $cap, $grant = true ) {
if ( ! isset( $this->roles[$role] ) )
return;
$this->roles[$role]['capabilities'][$cap] = $grant;
if ( $this->use_db )
update_option( $this->role_key, $this->roles );
}
It updates the $this->roles
object, but we can also see that the database will be updated each time our code runs, even if our new capability has already been registered!
它会更新$this->roles
对象,但即使在我们已经注册了新功能的情况下,我们也可以看到每次代码运行时都会更新数据库!
This means that if we care about performance, all the code we produce to customize roles and capabilities should not run on each page load.
这意味着,如果我们关心性能,则我们为定制角色和功能而定制的所有代码都不应在每次页面加载时都运行。
解决方法 (Workarounds)
There are several options to avoid these database problems.
有几种选择可以避免这些数据库问题。
使用插件激活 (Working with Plugin Activation)
WordPress allows plugin authors to trigger code when a plugin is enabled from the backend, by using the register_activation_hook()
function.
WordPress允许插件作者使用register_activation_hook()
函数从后端启用插件时触发代码。
Let’s create a sample plugin:
让我们创建一个示例插件:
/*
Plugin Name: Our sample role plugin
*/
register_activation_hook(__FILE__, function()
{
$role = add_role('plugins_manager', 'Plugins Manager', array());
$role->add_cap('install_plugins');
});
This code would run only once, when enabling the plugin on the website.
在网站上启用插件时,此代码将仅运行一次。
Now, we have to keep in mind that this solution depends on plugin activation and deactivation.
现在,我们必须记住,此解决方案取决于插件的激活和停用。
What would occur if the plugin is already in production, or if its reactivation is omitted when pushing the update?
如果插件已经在生产中,或者在推送更新时忽略了重新激活,将会发生什么?
In fact, this solution depends on the database too, and requires an extra step when pushing code.
实际上,此解决方案也取决于数据库,并且在推送代码时需要额外的步骤。
绕过WordPress数据库 (Bypassing the WordPress Database)
There is a second, undocumented solution, that can work well in some cases.
还有另一个未记录的解决方案,在某些情况下可以很好地工作。
Let’s have a last look at the WordPress core, when the WP_Roles
object loads the roles from the database on WordPress boot:
让我们最后看一下WordPress核心,当WP_Roles
对象在WordPress启动时从数据库加载角色时:
protected function _init() {
global $wpdb, $wp_user_roles;
$this->role_key = $wpdb->get_blog_prefix() . 'user_roles';
if ( ! empty( $wp_user_roles ) ) {
$this->roles = $wp_user_roles;
$this->use_db = false;
} else {
$this->roles = get_option( $this->role_key );
}
Before getting the data from the database, WordPress checks for the $wp_user_roles
global variable.
在从数据库中获取数据之前,WordPress将检查$wp_user_roles
全局变量。
If set, WordPress will use its content, and block database usage by setting the $this->use_db
variable to false
.
如果设置,WordPress将使用其内容,并通过将$this->use_db
变量设置为false
来阻止数据库使用。
Let’s try this, by keeping only a new, restricted administrator
role:
让我们通过仅保留一个新的受限administrator
角色来进行尝试:
/*
Plugin Name: Our sample role plugin
*/
$GLOBALS['wp_user_roles'] = array(
'administrator' => array(
'name' => 'Administrator',
'capabilities' => array(
'activate_plugins' => true,
'read' => true,
)
)
);
When loading the backend, we can see it has kept the definition of our custom role:
加载后端时,我们可以看到它保留了自定义角色的定义:
This solution solves the database problem, but may introduce some others:
此解决方案解决了数据库问题,但可能会引入其他一些问题:
- Plugins which use the native API may not behave correctly. 使用本机API的插件可能无法正常运行。
- We have to manually set the definition of each role, even the ones we don’t want to change. 我们必须手动设置每个角色的定义,甚至是我们不想更改的角色。
However, when building a custom WordPress application that needs a custom, static list of roles, this could be a possible solution:
但是,在构建需要自定义静态角色列表的自定义WordPress应用程序时,这可能是一种解决方案:
- The roles definition can be versioned with the code. 可以使用代码对角色定义进行版本控制。
- Pushing new code on an environment will automatically update the definition. 在环境中推送新代码将自动更新定义。
- No more questions about the database. 没有关于数据库的更多问题。
结论 (Conclusion)
In this article, I’ve presented an overview of roles and capabilities usage in WordPress.
在本文中,我对WordPress中的角色和功能使用进行了概述。
Although its complete API allows us to do almost whatever we want, the relation to the database remains the main concern.
尽管其完整的API使我们几乎可以做任何我们想做的事,但与数据库的关系仍然是主要问题。
We’ll have to keep this in mind when developing our plugins and themes.
在开发插件和主题时,我们必须牢记这一点。
What do you think about the way WordPress manages roles? I look forward to your feedback!
您如何看待WordPress管理角色的方式? 期待您的反馈!
翻译自: https://www.sitepoint.com/mastering-wordpress-roles-and-capabilities/
wordpress 功能