You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress Gutenberg获取学生列表权限拒绝与Promise挂起问题

方案选择结论

选第二种自定义REST API路由的方案就行。第一种原生getUsers()的方案不是不能修,但是要改核心用户查询接口的权限,改完之后所有学生角色都能访问全站用户的查询接口,很容易泄露管理员、其他用户的敏感信息,安全风险太高。自定义路由可以自己控制返回字段、访问权限,灵活度和安全性都好很多。


第一种方案的问题(不推荐使用)

除了权限问题,你贴的第一种代码本身还有低级变量错误:定义的用户列表变量叫authors,后面加载判断、列表遍历全错写成了posts,就算权限放开也会直接报变量未定义。
如果硬要修这个方案,需要加钩子放开学生角色对用户接口的访问权限,但非常不建议这么做,等于给学生开了全站用户数据的查询入口,后续很容易出数据泄露问题。


第二种方案的问题修复

你之前的代码Promise一直pending、接口不通,是四个核心问题导致的:

  • REST路由注册没挂到指定钩子,也没配权限回调,路由根本没生效
  • wp_localize_script绑错了脚本句柄,前端拿不到你传的nonce配置
  • 前端api-fetch的调用方式错了,已经import了apiFetch还去全局wp对象下找,nonce中间件配置不生效
  • 接口回调没返回标准REST响应格式,也没做「排除当前登录用户」的逻辑

第一步:修复PHP端代码

注意把代码里的脚本句柄换成你自己项目里注册Gutenberg插件JS时用的句柄:

// 给Gutenberg编辑器脚本传接口配置
add_action( 'enqueue_block_editor_assets', function() {
    // 替换成你实际用wp_enqueue_script加载Gutenberg插件的脚本句柄
    $script_handle = 'ccn-gut-script';
    wp_localize_script( $script_handle, 'wpApiSettings', [
        'root'  => esc_url_raw( rest_url() ),
        'nonce' => wp_create_nonce( 'wp_rest' )
    ]);
} );

// 注册自定义接口,必须挂在rest_api_init钩子上
add_action( 'rest_api_init', 'student_api_rest' );
function student_api_rest() {
    register_rest_route( 'api/v1', '/students', [
        'methods'             => 'GET',
        'callback'            => 'student_api_results',
        // 权限校验:登录用户即可访问,要限制仅学生访问就把判断改成in_array('student', wp_get_current_user()->roles)
        'permission_callback' => function() {
            return is_user_logged_in();
        }
    ] );
}

// 接口查询逻辑
function student_api_results( $request ) {
    $current_uid = get_current_user_id();
    // 直接在查询层排除当前登录用户,只返回需要的id和显示名字段,不返回敏感信息
    $students = get_users( [
        'role'    => 'student',
        'fields'  => [ 'ID', 'display_name' ],
        'exclude' => [ $current_uid ]
    ] );

    $format_data = [];
    foreach ( $students as $stu ) {
        $format_data[] = [
            'id'   => $stu->ID,
            'name' => $stu->display_name
        ];
    }

    return rest_ensure_response( $format_data );
}

第二步:修复前端Gutenberg代码

把你原来的组件代码替换成下面的版本,修了变量错误、加了加载状态、补了空值兜底:

import { __ } from '@wordpress/i18n';
import { CheckboxControl, Spinner } from '@wordpress/components';
import { registerPlugin } from '@wordpress/plugins';
import { PluginDocumentSettingPanel } from '@wordpress/edit-post';
import { useSelect } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';
import { useState, useEffect } from '@wordpress/element';
import apiFetch from '@wordpress/api-fetch';

// 配置nonce校验
apiFetch.use( apiFetch.createNonceMiddleware( wpApiSettings.nonce ) );

const MetaboxStudents = () => {
    const postType = useSelect( select => select( 'core/editor' ).getCurrentPostType(), [] );
    if ( postType !== 'subject-imposed' ) return null;

    const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );
    const [ students, setStudents ] = useState( null );

    // 组件加载时拉取学生列表
    useEffect( () => {
        apiFetch( { path: '/api/v1/students' } )
            .then( res => setStudents( res ) )
            .catch( err => console.error( '学生列表加载失败:', err ) );
    }, [] );

    // 复选框选值逻辑
    const handleCheck = ( userId ) => {
        const checkedList = meta._metafield_students || [];
        setMeta( {
            _metafield_students: checkedList.includes( userId )
                ? checkedList.filter( id => id !== userId )
                : [ ...checkedList, userId ]
        } );
    };

    return (
        <PluginDocumentSettingPanel
            name="list-students"
            title={ __( 'List of students', 'ccn-gut' ) }
            className="editor-styles-metabox"
        >
            <div className="gut-checkboxes-group">
                { !students && <Spinner /> }
                { students?.map( user => (
                    <CheckboxControl
                        label={ user.name }
                        key={ `student-${user.id}` }
                        checked={ (meta._metafield_students || []).includes( user.id ) }
                        onChange={ () => handleCheck( user.id ) }
                    />
                ) ) }
            </div>
        </PluginDocumentSettingPanel>
    );
};

registerPlugin( 'plugin-document-students', {
    render: MetaboxStudents,
    icon: null
} );

几个容易踩的小坑

  • 确认你的文章类型subject-imposed已经开启了custom-fields支持,不然meta字段存不进去
  • 接口写完可以先直接在浏览器访问你的域名/wp-json/api/v1/students,确认能正常返回数据再调试前端
  • 如果nonce校验失败,去检查wp_localize_script绑定的脚本句柄是不是和你加载Gutenberg插件的句柄完全一致,句柄不对的话前端拿不到wpApiSettings变量,请求直接401

内容的提问来源于stack exchange,提问作者Jandon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 18:48:41