承接上文,本节主要解决两个问题,
- 菜单权限控制 – 仅限访问指定菜单和仅限指定人员访问菜单
- 指定菜单页加载 CSS 和 JS
问题
本节围绕以下两个常见问题进行展开
权限控制
虽然默认的权限控制已经好用,但有时,我们希望只有指定 ID 的用户才能访问菜单。
比如,在我开发退款插件时,为了控制退款员工的权限,我只让他们访问 退款 菜单,其他菜单都拒绝访问,避免造成其他影响。
我可不希望退款员工删除网站首页,那就糟糕了
但是,只有管理员才有退款权限
加载 JS 和 CSS
默认的加载方式是在所有菜单页面上都加载 JS 和 CSS 资源,当加载的资源过多,会造成所有菜单页都会卡顿。
这点太不好了,该省省,该花花,这点浏览器资源,还是很有必要节省的。
通过在指定的菜单上才加载资源,可以有效的节省浏览器资源,提升后台页面访问速度。
后台一般是给管理者使用的,一般不太在乎页面加载速度,但是,这个是可以省的,我们还是节省下吧
流程
仅限指定用户可访问此菜单
获取用户ID
一般用户 ID 是设置选项给出的一个数组,这里我们进行简化,直接从用户列表中拿几个用户 ID 组成数组。
在用户列表中,选择你需要获取的用户,鼠标点击编辑按钮,
在 URL 中,注意这个 user_id
字段
http://localhost:10004/wp-admin/user-edit.php?user_id=2&wp_http_referer=%2Fwp-admin%2Fusers.php
其中,user_id
后面的值,就是用户 ID 了,我们凭借这个值,来判断当前访问的用户。
我们将需要控制的用户 ID 组成数组
$a = array(1,
2,
3,
4,
5,
6);
// 示例数组,存储若干用户ID
添加判断
还记得之前讲到,是如何创建顶级菜单的嘛?实例代码如下
//创建一个菜单
function vuespa_create_menu_page()
{
add_menu_page(
'VueSpa选项',
// 此菜单对应页面上显示的标题
'VueSpa',
// 要为此实际菜单项显示的文本
'administrator',
// 哪种类型的用户可以看到此菜单
'vuespa_id',
// 此菜单项的唯一ID(即段塞)
'vuespa_menu_page_display',
// 呈现此页面的菜单时要调用的函数的名称
'dashicons-admin-customizer',
//图标 - 默认图标
'500.1',
//位置
);
}
// end vuespa_create_menu_page
add_action('admin_menu',
'vuespa_create_menu_page');
我们对其添加一个判断,若当前访问菜单的人是指定的用户 ID,则输出空值,不显示菜单。
判断条件如下:
if
(
current_user_can('administrator')
&& is_array($a)
&& in_array(get_current_user_id(), $a)
)
{}
- 判断是否拥有管理员权限(可按需设置)
- 并且,变量
$a
是否是数组 - 并且,当前访问菜单的用户 ID 是否在数组
$a
中。
只有当前访问菜单的用户 ID 符合以上所有需求,才会展示菜单。
is_array()
用于类型检查,提升代码健壮性
示例
//创建一个菜单
function vuespa_create_menu_page()
{
//控制权限的员工 ID
$a = array(1,
2,
3,
4,
5,
6);
// 示例数组,存储若干用户ID
//权限判断
if
(
current_user_can('administrator')
&& is_array($a)
&& in_array(get_current_user_id(), $a)
)
{
add_menu_page(
'VueSpa选项',
// 此菜单对应页面上显示的标题
'VueSpa',
// 要为此实际菜单项显示的文本
'administrator',
// 哪种类型的用户可以看到此菜单
'vuespa_id',
// 此菜单项的唯一ID(即段塞)
'vuespa_menu_page_display',
// 呈现此页面的菜单时要调用的函数的名称
'dashicons-admin-customizer',
//图标 - 默认图标
'500.1',
//位置
);
}
}
// end vuespa_create_menu_page
add_action('admin_menu',
'vuespa_create_menu_page');
现在,我们开发的这个菜单,即使是管理员来了,也只有指定的管理员才能访问。
指定用户仅限访问指定菜单
业务介绍:
在开发退款插件时,只有管理员才有退款权限,所以,只能给退款员工以管理员权限。
但是为了防止退款员工进行除退款外的其他操作,我们需要限制退款员工只能访问退款菜单。
流程
- 提供的变量是否是数组
- 当前访问的用户ID是否在提供数组中
- 获取当前链接的 page 字段,是否是指定菜单
- 如果是 admin-ajax.php 或 admin-post.php,则不拦截
- 符合以上全部信息,则拦截,并提供提示信息
对于第四点,如果我们当前在限制的菜单中,当我们要进行数据查询或保存数据等操作,会通过以上两个文件发出请求,这会因为不符合第3个条件而被拦截,这里做个例外。
示例代码
以下代码可供参考
//权限管理
add_action('admin_init',
'mqzj_restrict_access');
function mqzj_restrict_access()
{
$user = wp_get_current_user();
$a = array(1,
2,
3,
4,
5,
6);
// 示例数组,存储若干用户ID
// 如果 $a 为空或为字符串,则将其赋值为空数组
if
(empty($a)
|| is_string($a))
{
$a = array();
}
//是限定 ID
if
(in_array($user->ID, $a))
{
//在访问限定菜单
if
((isset($_GET['page'])
&& $_GET['page']
==
'refund_querys')
||
(isset($_GET['page'])
&& $_GET['page']
==
'npcink_orders_list'))
{
return;
} elseif (
// 如果是 admin-ajax.php 或 admin-post.php,则不拦截
preg_match('/^/wp-admin/(admin-ajax.php|admin-post.php)/', $_SERVER['PHP_SELF']))
{
return;
}
else
{
//跳转
$adminPage = get_admin_url()
.
'admin.php';
$refundPage = get_admin_url()
.
'index.php';
$message =
'
您暂无授权访问此页面,请联系管理员授权!
<ul>
<li>
<a href="'
.%20$adminPage%20.
'?page=npcink_orders_list">订单管理</a>
</li>
<li>
<a href="'
.%20$refundPage%20.
'?page=refund_querys">订单退款</a>
</li>
</ul>
';
wp_die($message);
exit;
}
}
}
上面仅允许访问和提示的菜单如下
https://www.npc.ink/wp-admin/index.php?page=refund_querys
https://www.npc.ink/wp-admin/admin.php?page=npcink_orders_list&order_state=f
相信你已经掌握了其中的思路,留一个思考题,
你知道如何禁止访问评论菜单,比如这样的链接
https://www.npc.ink/wp-admin/edit-comments.php
欢迎您在评论区中给出答案。
控制 JS 和 CSS 在菜单中的加载
加载资源
我们一般加载上述资源是这样写的
function vuespa_load_vues($hook)
{
//版本号
$ver =
'66';
//加载到页面顶部
wp_enqueue_style('vite', plugin_dir_url(__FILE__)
.
'vites/dist/index.css', array(), $ver,
false);
//加载到页面底部
wp_enqueue_script('vite', plugin_dir_url(__FILE__)
.
'vites/dist/index.js', array(), $ver,
true);
}
//样式加载到后台
add_action('admin_enqueue_scripts',
'vuespa_load_vues');
这样,我们就在所有后台的所有页面上,加载了上述资源。
获取 $hook
还记得之前创建菜单时,每个菜单都有唯一的 slug
嘛?每个菜单页面也是有唯一的 $hook
的。
我们可以通过以下代码获取当前菜单的 $hook
值。
function wpdocs_myselective_css_or_js( $hook )
{
echo '<h1 style="color: crimson;text-align: center;">'
. esc_html( $hook )
.
'</h1>';
}
add_action(
'admin_enqueue_scripts',
'wpdocs_myselective_css_or_js'
);
打开我们需要获取的菜单页面,效果如下
进行判断
有了唯一值,剩下的交给判断就好了。
function vuespa_load_vues($hook)
{
//判断当前页面是否是指定页面,是则继续加载
if
('toplevel_page_vuespa_id'
!= $hook)
{
return;
}
//版本号
$ver =
'53';
//加载到页面顶部
wp_enqueue_style('vite', plugin_dir_url(__FILE__)
.
'vites/dist/index.css', array(), $ver,
false);
//加载到页面底部
wp_enqueue_script('vite', plugin_dir_url(__FILE__)
.
'vites/dist/index.js', array(), $ver,
true);
}
//样式加载到后台
add_action('admin_enqueue_scripts',
'vuespa_load_vues');
通过上述代码中的 if 判断,就只会在符合要求的 $hook 菜单上加载资源了。
总结
本节关注菜单权限方面,进行了菜单展示权限和菜单中加载资源的研究,这是我们日常开发中常用的功能。
通过上述两个权限的适当配合,可以一定程度上解决部分安全问题和页面加载缓慢的问题。
关于 WordPress 菜单的主要内容,到此为止,后续会根据实际问题,不定期更新相关内容。