Search code examples
wordpressadvanced-custom-fields

acf/load_field containing wp query causes page attributes box to become empty


I have the following code that populates an ACF checkbox list with the ID (as value) and title (as label) of each Video custom post type post. The function is working and outputs the list as it should be, however when in use, the function causes the page attributes box to become empty, i.e. no page parent or template dropdowns (see image below). When I remove the if( $videos->have_posts() ) section, the error disappears. Removing the code inside the loop does not fix the error.

Here is my full code:

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;

Here is how the error looks on the page edit screen

How the error looks

I have tried:

  • Removing wp_reset_postdata()
  • Swapping wp_reset_postdata() for wp_reset_query()
  • Changing the variable name $videos

Any thoughts?


Solution

  • Managed to find a solution after all. I'm not sure why this works, so if anyone can shed some light then that would be much appreciated!

    The solution was to manually reset the $post variable after the loop, as below:

    if ( !function_exists('populate_available_videos') ):
    
        add_filter('acf/load_field/name=available_videos', 'populate_available_videos');
    
        function populate_available_videos( $field ){
    
            // Store original $post variable
            global $post;
            $orig_post = $post;
    
            // 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);
    
            if( $videos->have_posts() ) : while( $videos->have_posts() ) : $videos->the_post();
    
                $field['choices'][get_the_ID()] = get_the_title();
    
            endwhile; endif;
    
            // Reset $post variable from saved original version
            $post = $orig_post;
            wp_reset_postdata();
    
            return $field;
        }
    
    endif;