Unable to create form if field group contains dynamic content

[ad_1]

Hello,

Thanks for the feedback!

The problem come from the usage of WP_Query inside the acf/load_field hook, which is executed everywhere, including in the WP Admin panel and thus in the ACFE Form UI.

There is a 11 years old bug which prevent WP_Query & wp_reset_postdata() to work correctly in the WP Admin panel.

See the related core trac ticket #18408. The current developer motto is to not use them in the admin panel.

From the ticket discussion:

The root issue is that wp_reset_postdata() is designed to reset globals to match the main query. But in the case of post.php, there is no main query – the $post global is populated manually, using get_post(), rather than through the normal $wp_query loop.

The preferred method is to use get_posts() instead, which doesn’t override the global $post object.

Here are some solutions in order to fix your code:

Solution 1: Use get_posts()

This is the most safe method. It is also faster than the WP_Query. Usage example:

add_filter('acf/load_field/name=associated_account', 'acf_load_associated_account_field_choices');
function acf_load_associated_account_field_choices($field){
    
    // reset choices
    $field['choices'] = array();
    
    // query accounts
    $accounts = get_posts(array(
        'posts_per_page' => -1,
        'post_type'      => 'accounts',
        'fields'         => 'ids' // return post ids only
    ));
    
    foreach($accounts as $post_id){
    
        // get values
        $value = get_post_field('post_name', $post_id);
        $label = get_post_field('account_name', $post_id);
    
        // append to choices
        $field['choices'][ $value ] = $label;
        
    }
    
    // return
    return $field;
    
}

Solution 2: Clone the global $post and re-assign it

If you really want to keep using WP_Query, then you can clone the global $post and re-assign it once you finished using it. Usage example:

add_filter('acf/load_field/name=associated_account', 'acf_load_associated_account_field_choices');
function acf_load_associated_account_field_choices($field){
    
    // get global post
    global $post;
    
    // clone original post
    $_post = $post;
    
    // reset choices
    $field['choices'] = array();
    
    // query accounts
    $my_query = new WP_Query(array(
        'posts_per_page' => -1,
        'post_type'      => 'accounts'
    ));
    
    if($my_query->have_posts()){
        while($my_query->have_posts()){
            $my_query->the_post();
            
            // get values
            $value = get_post_field('post_name', get_the_ID());
            $label = get_post_field('account_name', get_the_ID());
            
            // append to choices
            $field['choices'][ $value ] = $label;
            
        }
        
        wp_reset_postdata();
    }
    
    // re-assign global post back to default
    $post = $_post;
    
    // return
    return $field;
    
}

A note on the usage of acf/load_field

I would not recommend to use the acf/load_field hook in order to populate field choices, unless you have some work to do with Ajax Queries.

In fact, as explained earlier, this is hook is executed everywhere, on every page load. Which means that your query will slow down your website and your admin panel since it will retrieve all posts from the accounts post type.

Also, you’ll see that the dynmically populated choices will appear in the ACF Field Group UI, when you edit the associated_account field. Those choices will be also exported in the Json/PHP if you export your Field Group with the ACF tools. This is really not optimized.

Instead, I would recommend to use the acf/prepare_field, which works the exact same way but is only executed on the Post Edit screen when the field is actually printed on the page.

So here is my final optimized solution of your code:

add_filter('acf/prepare_field/name=associated_account', 'acf_prepare_associated_account_field_choices');
function acf_prepare_associated_account_field_choices($field){
    
    // reset choices
    $field['choices'] = array();
    
    // get accounts
    $accounts = get_posts(array(
        'posts_per_page' => -1,
        'post_type'      => 'accounts',
        'fields'         => 'ids' // return post ids only
    ));
    
    foreach($accounts as $post_id){
        
        // get values
        $value = get_post_field('post_name', $post_id);
        $label = get_post_field('account_name', $post_id);
        
        // append to choices
        $field['choices'][ $value ] = $label;
        
    }
    
    // return
    return $field;
    
}

Hope it helps!

Have a nice day!

Regards.

 

This site will teach you how to build a WordPress website for beginners. We will cover everything from installing WordPress to adding pages, posts, and images to your site. You will learn how to customize your site with themes and plugins, as well as how to market your site online.

Buy WordPress Transfer