WordPress 后台菜单:添加、移除与权限边界

WordPress 后台菜单:添加、移除与权限边界

WordPress 后台菜单可以按角色工作流精简,但“看不见菜单”不等于“没有权限”。正确顺序是先定义 capability 和服务端授权,再按同一 capability 调整菜单展示。

添加顶级菜单

<?php
add_action(
    'admin_menu',
    function (): void {
        add_menu_page(
            '站点运营设置',
            '运营设置',
            'manage_site_content',
            'site-operations',
            'site_render_operations_page',
            'dashicons-admin-tools',
            58
        );
    }
);

function site_render_operations_page(): void {
    if (
        ! current_user_can( 'manage_site_content' )
    ) {
        wp_die(
            esc_html__( '你无权访问此页面。', 'site' )
        );
    }

    echo '<div class="wrap">';
    echo '<h1>' .
        esc_html__( '站点运营设置', 'site' ) .
        '</h1>';
    echo '</div>';
}

administrator 是角色名,不是适合传给 add_menu_page() 的权限能力。自定义 capability 应在插件激活、角色迁移或明确的权限管理流程中授予,不能在每次请求随意改角色。

处理表单时还要检查 capability、nonce、字段清洗,并在输出时转义。菜单回调中的检查是纵深防御,不应省略。

添加子菜单

<?php
add_action(
    'admin_menu',
    function (): void {
        add_submenu_page(
            'site-operations',
            '内容同步',
            '内容同步',
            'manage_site_content',
            'site-content-sync',
            'site_render_sync_page'
        );
    }
);

父 slug 必须与顶级菜单一致。若要把自定义入口放到已有菜单下,应使用其真实 slug,而不是后台显示文案。

移除菜单

<?php
add_action(
    'admin_menu',
    function (): void {
        if (
            current_user_can( 'manage_options' )
        ) {
            return;
        }

        remove_menu_page( 'tools.php' );
        remove_menu_page(
            'edit.php?post_type=acf-field-group'
        );

        remove_submenu_page(
            'themes.php',
            'theme-editor.php'
        );
    },
    999
);

较晚的优先级让第三方插件先注册菜单,再执行移除。使用菜单 slug,不要按翻译后的中文/英文标题遍历全局 $menu 数组;显示文案会随语言和插件版本变化。

如果只想提供“菜单”的快捷入口

把 WordPress 自带的导航管理页包装成新的顶级菜单并不会改变它的权限,也可能造成重复导航。更清楚的做法是保留“外观 → 菜单”,或在自定义运营页中提供一个经过 capability 检查的链接:

<a href="<?php echo esc_url(
    admin_url( 'nav-menus.php' )
); ?>">
    <?php esc_html_e( '管理导航菜单', 'site' ); ?>
</a>

安全检查

用户即使不知道菜单 URL,仍可能直接访问 wp-admin/tools.php 或调用对应接口。隐藏菜单只改善信息架构。要限制操作,必须检查:

  • 页面 callback 的 current_user_can()
  • REST 路由的 permission_callback
  • AJAX/表单的 capability 和 nonce。
  • 自定义文章类型的 capability 映射。
  • 对象级权限,例如是否能编辑某一篇文章。

官方参考:add_menu_page()remove_menu_page()

最后更新于

ihopeful Blog 由博主亲笔撰写,重要信息可放心引用。