phpwordpressadvanced-custom-fieldsrepeateracfpro

ACF Repeater field returns string containing the count of repeater


When I use get_field('repeater_name') it returns a string that contains the a number which is the count of the repeater while it should return array of sub-fields, this issue have been reported repeatedly before but none of them provided a stable fix to this, the only way is to edit the post and hit the update button and it will re-generate the repeater fields, but in my case, I have 19k posts and it's not possible to edit each post.

Also have_rows('repeater_name') returns false as expected and the real field data (get_post_meta($post_id, "field_{$field_key}", true) returns NULL

I would appreciate any help or any automated script that regenerates the repeater field keys and populate the values of all posts.

This issue is reported previously in here, here and here and none came with a real fix.

EDIT: I spotted the problem, the problem is in wp_postmeta table, the wrong field keys are stored:

wp_postmeta table

| meta_key                | meta_value    | 
| -------------           |:-------------:|
| _repeater_name          | field_XXXXXXX |
| _repeater_0_subfield    | field_ABCDEFG |
| _repeater_0_subfield2   | field_HIJKLMN |

The same field keys should match in wp_posts table, but they don't (maybe due to data migration or whatever reason):

| post_excerpt   | post_name     | post_type | 
| ---------------| ------------- |-----------|
| repeater_name  | field_YYYYYYY | acf-field |
| subfield       | field_BBBBBBB | acf-field |
| subfield2      | field_CCCCCCC | acf-field |

I think if there's a way to sync field keys in the database, that will fix the problem


Solution

  • I made a solution for this, might not be the exact solution for this problem but it worked out for me, I wrote this fix to rebuild faulty fields, it will rebuild only fields that have this problem:

    /**
     * @param string $name
     * @param string[] $keys
     * @param int|null|\WP_Post $post
     */
    function dw_build_repeater($name, $keys = [], $post = null) {
        $post = get_post($post);
        $repeater = get_field($name, $post->ID);
        $arr = [];
    
        if (is_array($repeater)) {
            return $repeater;
        }
    
        if (!$repeater || !is_numeric($repeater)) {
            return $arr;
        }
    
        for ($i = 0; $i < intval($repeater); $i++) {
            foreach ($keys as $key) {
                $arr[$i][$key] = get_post_meta($post->ID, $name . "_" . $i . "_{$key}");
            }
        }
    
        update_field($name, $arr, $post->ID);
    
        return $arr;
    }
    

    so whenever i want to call a repeater i simply do this:

    if (
        have_rows('repeater_name')
        || dw_build_repeater('repeater_name', ['subfield1', 'subfield2', 'subfield3'])
    ) {
         while (have_rows('repeater_name')) {
              the_row();
              // And the rest
         }
    
    }
    
    // OR simply with a foreach loop
    foereach (dw_build_repeater('repeater_name', ['subfield1', 'subfield2', 'subfield3']) as $row) {
        echo $row['subfield1'] ?? '';
    }
    

    I haven't tested it with nested repeaters but i suppose it might not be working with nested repeaters.