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

使用WP_Query的acf/load_field钩子导致页面属性框为空

问题:ACF字段填充代码导致页面属性框为空

我编写了一段代码,用于将自定义文章类型Video的ID(作为值)和标题(作为标签)填充到ACF复选框列表中。该功能可正常输出列表,但启用后会导致页面编辑界面的页面属性框为空——没有父页面或模板下拉选项。移除if( $videos->have_posts() )代码段后,问题消失;仅移除循环内代码无法解决问题。

完整代码

if ( !function_exists('populate_available_videos') ):

    add_filter('acf/load_field/name=available_videos', 'populate_available_videos');

    function populate_available_videos( $field ){

        // reset choices
        $field['choices'] = array();

        $args = array(
            'post_type'         => 'video',
            'posts_per_page'    => -1,
            'post_status'       => 'publish',
            'orderby'           => 'menu_order',
        );

        $videos = new WP_Query($args);

        // Removing this loop fixes the error

        if( $videos->have_posts() ) : while( $videos->have_posts() ) : $videos->the_post();

            // Removing just this does not fix the error
            
            $field['choices'][get_the_ID()] = get_the_title();

        endwhile; wp_reset_postdata(); endif;

        return $field;
    }

endif;

错误表现

页面编辑界面的页面属性区域完全为空,既没有父页面选择下拉框,也没有模板选择下拉框。

已尝试的解决方法

  • 移除wp_reset_postdata()
  • 将wp_reset_postdata()替换为wp_reset_query()
  • 修改变量名$videos

解决方案

问题根源在于the_post()方法会修改WordPress全局的$post对象,而页面属性框的渲染逻辑同样依赖这个全局对象。即便调用了wp_reset_postdata(),在ACF字段加载的时机下,全局状态可能无法正确恢复,从而干扰页面属性的正常渲染。

正确的做法是避免使用the_post()循环,直接遍历查询结果的posts数组,不触碰全局$post:

修改后的代码:

if ( !function_exists('populate_available_videos') ):

    add_filter('acf/load_field/name=available_videos', 'populate_available_videos');

    function populate_available_videos( $field ){
        // 重置选项
        $field['choices'] = array();

        $args = array(
            'post_type'         => 'video',
            'posts_per_page'    => -1,
            'post_status'       => 'publish',
            'orderby'           => 'menu_order',
        );

        $videos = new WP_Query($args);

        // 直接遍历posts数组,不修改全局post对象
        if ( !empty($videos->posts) ) {
            foreach ( $videos->posts as $video_post ) {
                $field['choices'][$video_post->ID] = $video_post->post_title;
            }
        }

        // 重置查询状态(可选,但养成好习惯)
        wp_reset_postdata();

        return $field;
    }

endif;

原理说明

通过直接访问$videos->posts中的文章对象,我们可以直接获取ID和标题,完全不需要调用the_post()来切换全局上下文。这种方式不会干扰任何依赖全局$post的功能,自然就解决了页面属性框为空的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 02:15:02