Repeater Fields and ACF Integration

The Challenge

Any Pro license includes a Create Post form action that provides you with the ability to allow users to create posts, pages, and custom post types from the front-end of your site. Your users may also manage and edit their posts through the Formidable form that was used to create the post.

If you're an Advanced Custom Fields user, it should excite you to know that another nice feature delivered with the Create Post form action is functionality that integrates your form's fields with the very popular ACF Pro plugin right out of the box. This feature raises questions though:

Is there a way to map a Formidable repeater to ACF repeater?

Ben Rose—Formidable Slack Community #code-help Channel

This is a commonly asked question that Formidable's knowledge base documentation addresses this way:

…the more advanced field types like the repeater field, currently require custom code for integration.

Formidable Knowledge base—Integrate with Advanced Custom Fields (ACF)

As you know, Formidable Pro includes a repeater field. So does ACF. But what custom code do you use to integrate the two field types with each other?

Sadly, there is no custom code example available in the knowledge base article to demonstrate how this integration should be handled. Hopefully, this article addresses Ben Rose's question.

The Solution

Before we delve into writing code, one thing we're not going to address in this article is how the Formidable repeater field works on the front end. We've already covered that topic in detail in Repeaters and Complex jQuery Operations. If you haven't read the article or want to learn more about how Formidable's repeater field works, please take the time to visit the link.

Four Steps

There are four steps to integrating Formidable Pro's repeater field with ACF:

  1. Configure the ACF repeater
  2. Add a repeater field to a Formidable form
  3. Configure the Create Post form action
  4. Write the custom PHP code

Step 1. Configure the ACF Repeater

This section does not provide step-by-step instructions for configuring an ACF repeater. There's plenty of material, including a nicely done video, for learning about repeaters on the ACF web site. Click the link to learn more about repeaters.

For this tutorial, we've created an ACF field group consisting of a single repeater with three fields: name, city, and state. For simplicity's sake, they are all text fields.

ACF repeater with three text fields

We've assigned this field group to a custom post type called Repeater.

ACF field group assigned to custom post type named Repeater

Step 2. Add a Repeater Field to a Formidable Form

The form is very simple with just three fields: title, post content, and the repeater. The repeater has three text fields that match the text fields in the ACF repeater: name, city, and state.

Simple form with repeater field

Step 3. Configure the Create Post Form Action

For the Create Post form action, we'll be creating a custom post type named Repeater so we can segregate these test posts from other types of content.

In order to create a custom post type (CPT) through the Formidable Pro Create Post form action, the CPT has to already exist in your system otherwise it won't show up in the Post Type dropdown list. If you don't know how to create a CPT, Google it or search the WordPress repository for a plugin that can create a CPT for you. There's a lot of information in the wild about CPTs.
Create Post Form Action Setup

The Action Name is Create Repeater Field. The Post Title receives the content of the form's Title input and the Post Content gets the value of the Post Content input field.

Save your form, add it to a page or post, and test that a CPT is created as expected.

Step 4. Write the Custom PHP Code

Now that you've successfully tested your form and created a new post, it's time to write our custom code and apply it through a Formidable hook. The best hook to use for this is the frm_after_create_entry action. The reason will become clear shortly.

If you're not familiar with WordPress hooks (actions and filters), it's important that you spend a little time learning about them. Many of the tutorials and advanced courses on this site make prominent use of actions and filters. It's easy to get lost if you don't have a working understanding of them. The Hooks section of the WordPress Plugin Handbook is a good place to start.

Database Architecture

Before we get into writing the actual code, it's important to understand a little about the way Formidable stores its entry content compared to how WordPress and ACF store their respective data elements because our custom code will be pulling data from Formidable and writing it directly to a WordPress table.

When a user creates a new form entry, Formidable stores all entry data in two tables: wp_frm_items and wp_frm_item_metas.

wp_frm_items is essentially a header record. wp_frm_item_metas contains the details of the form entry. In other words, the content for every field on your form is stored in a separate row in this table, one row per field. Each row is linked back to the header record.

If you're really a techno-geek, the structures of these tables as shown in PHPMyAdmin are:

Formidable's wp_frm_items table structure
wp_frm_items table structure
Formidable's wp_frm_item_metas table structure
wp_frm_item_metas table structure

WordPress and ACF on the other hand use different tables to store their content. These tables are wp_posts and wp_postmeta. These table structures are somewhat similar to Formidable's content tables in that wp_posts serves as a header record for custom field data that gets stored in wp_postmeta, one custom field per wp_postmeta row.

ACF Repeater Storage Schema

The ACF developers explain their repeater field storage schema this way:

The repeater field saves all its data in the wp_postmeta table. If your repeater field is called “gallery” and contains 2 sub fields called “image” and “description”, this would be the database structure of 2 rows of data:

ACF Repeater Field storage schema

The entire purpose of our custom code is to extract the data from Formidable in whatever format it is stored in, reformat it wp_postmeta, and write it to the wp_postmeta table as explain by the ACF developers.

The Basic Function

Earlier, we mentioned that we'll be using Formidable's frm_after_create_entry action hook to execute our custom code. The reason for this is because in order to write our repeater data to wp_postmeta, we have to use the WordPress add_post_meta function.

The add_post_meta function has three mandatory parameters and one optional parameter. We're going to ignore the optional parameter for this tutorial. The mandatory parameters are:

  1. $post_id—this is the id of the post created by the Create Post form action.
  2. $meta_key—the metadata name
  3. $meta_value—the metadata value. Must be serializable, if non-scalar.

If you're new to coding at this level, I'm sure that the third parameter is making your head spin. A scalar variable, or scalar field, is a variable that holds one value at a time. Basically, it's a standard input field.

Serializing is required if a field stores multiple values such as multi-select checkbox or dropdown may. We won't be serializing data in this lesson. To learn more about this visit the WordPress maybe_serialize function page.

Now back to the reason for using frm_after_create_entry. Since the first mandatory parameter for add_post_meta is $post_id and the post id doesn't exist until the post is created, the only hook that allows us to retrieve the post id from Formidable is frm_after_create_entry. It would be nice if there was a frm_after_create_post action, but that's just wishful thinking.

This first part of our custom function retrieves the post id.

Let's explain the code. The frm_after_create_entry action fires for every Formidable form on your site. The 30, 2 means our action runs at priority 30 and the associated function has 2 parameters. So the first step is to limit this action to the form that has our repeater. In the case of the form on our development site, the form id is 30. You have to change this id to the id of your form.

The second step is to retrieve the form entry. We're using Formidable's built-in FrmEntry::getOne( $entry_id ) function to do that. The parameter is the $entry_id passed to our function by the action.

Next is the retrieval of the post id and a sanity check to back out of the function if the entry doesn't have an associated post id. The getOne function returns an object that contains all of the fields from the wp_frm_items table for a specific from entry. To get a visual of this, we'll use the Kint debugger to display the content returned by getOne:

Kint debugger showing content of $entry variable

As you can see, the post_id for the newly created post is 509. Now let's get to the Formidable repeater field.

Retrieve the Form's Repeater Field Content

There are a couple of ways to retrieve to the repeater field content. The first is how we don't want you doing it. That is using PHP's $_POST array, an associative array of variables passed to the current script via the HTTP POST method. In other words, when you click submit PHP takes all of the fields from your form and creates this array to hold all of your form entry data. This is automatic and $_POST persists until Formidable finishes processing your form submission.

To explain why we don't like using the $_POST array for this operation requires a visual. Look at this Kint view of the $_POST array content for our test form.

Kint view of PHP $_POST array

The data for the form inputs are within the item_meta array. The array element referenced by the 237 key is the title field. Correspondingly, 238 is the post content field, and 232 is the repeater field. Then there are three associated arrays to the repeater field. You have an array for row_ids, then an array for each of the individual rows. The 234, 235, and 236 elements are the field ids and content for the row inputs.

You could easily extract the data you need to populate the ACF repeater from the $_POST array. (Well, maybe not so easily.) The reason we don't recommend this is because of the KEY vs. ID argument when writing transportable code. If you've ever taken one of our courses or read any of our other programming articles, we strongly advocate for referencing keys in your code rather than ids. To learn more, see Writing Transportable Code: Keys vs. IDs.

Now let's look at how Formidable stores repeater data in its wp_frm_item_metas table:

PHPMyAdmin view of repeater rows stored in wp_frm_item_metas

If you recall from our $_POST array examination, our repeater field has the field id of 232. Look at how Formidable stores the content of our repeater field. What is that unintelligible content stored as the repeater's meta_value?

Formidable treats repeaters as an individual form similar to an embedded form. In truth, it is an embedded form. Internally, it has it's own form id and key. If you were to look into our wp_forms table, the repeater has a form_id of 31. Yet, the form we are working with has a form_id of 30.

When saving our form's data, Formidable writes each row of a repeater field as a separate entry for the embedded repeater form, which displays as a field on its parent form. The rows are saved first, then the entry ids of each row of data is stored in an array and saved as the meta_value for the repeater field. The meta_value for field 232 is a serialized representation of the item ids for the two rows of data we added to our repeater field.

This is a little bit difficult to understand at first, so let's go a little deeper. We entered two rows of data into our repeater. The first row is John Doe, Raleigh, North Carolina. The second row is Mickey Mouse, Orlando, Florida.

In the table content above, the first row is associated with item_id 361 and the second row with item_id 362 and our repeater field is linked to item_id 363. Because these are all form entries, there is a corresponding header record with these ids in wp_frm_items.

To finish our custom function, we need to get the content of the repeater field, convert it back to an array we can work with in code, loop through the array, retrieve the row content, format it for ACF, and finally write the new values to wp_postmeta. Simple, right?

Format the Data and Write to ACF's Repeater

Here's your finished custom code:

Conclusion

We really hope this gets you pointed in the right direction. Obviously, this tutorial doesn't address what happens if you edit a form entry, but at least it will get you started integrating the Formidable repeater with the ACF repeater. We'll leave the editing for another tutorial someday.

Reader Interactions

Leave a Reply

Your email address will not be published. Required fields are marked *

Comments

  1. Great Tutorial! Thank you very much! Just to be clear this works only one direction right? if i would update the post from wp-admin this wouldn’t be updated in the entry like other post fields right?

    • Thanks for the kind words Ben!

      Yes, you’re correct. This is one-way when the form entry is created only. The code can be modified to work with a different Formidable hook to allow form edits as well. As far as making changes in the CPT and having them update Formidable, that requires an entirely different approach that would be quite complex. I don’t see a tutorial for that happening anytime soon given my current workload.

    • We’re Formidable Experts here, not ACF experts. If you want to provide a code example of how this works with Formidable, we welcome your contribution.

      • Hi Victor,

        It appears that Anthony may not answer, so I thought I would. Both approaches work. Anthony’s approach would replace the three ‘add_post_meta’ function calls and, instead, make a single call to ACF’s ‘add_row()’ function passing an array of key=>value pairs. In your example, it would look like this:

        $row = array(
        $name_meta_key => $name_meta_value,
        $city_meta_key => $city_meta_value,
        $state_meta_key => $state_meta_value
        );

        add_row($acf_repeater, $row, $entry->post_id);

  2. How…HOW did I not find this website sooner?

    I spent DOZENS of hours going through the Formidable class files and documentation trying to find good ways to pull the data from repeater fields, unserialize it, and then add it back to another form. Formidable is incredibly powerful, but their documentation is limited for developers. THANK YOU for all the time and effort you’ve put into this website and, specifically, this tutorial. You will, undoubtedly, be saving me many, many hours, and I won’t be pulling my hair out nearly as much. Again, THANK YOU!

    • Hi Kris,

      Thank you for your encouraging comment. We’ve been working on this site for just about a year and haven’t officially launched it yet. There’s a still a few things we want to get accomplished before we officially start promoting it.

      Warm regard,

      Victor

  3. Fantastic, well-presented information. Will you do a tutorial on how to add ACF relationship fields to Formidable forms?

    • Hi Richard,

      Thank you for your comment. We appreciate it. We’re not experts with ACF here and haven’t thought any additional ACF related tutorials. Many of our tutorials either come from the projects we work on for clients or when enough people have shown an interest in a particular topic in Formidable related forum posts. The topic of this post derives from a question that has been asked many times on the old Formidable Community forum and in the Slack community. You’re the first one to ever ask about relationship fields. Hmmm…, just a though, but maybe I need to setup a “Tutorials You’d like to See” section where visitors can vote on topics of interest.

  4. Hi thanks for this, what if you have several forms e.g. I have a lot because of the conditionals. How would I add them all in one script? I am trying also to only allow one item from ACF to be checked. That is why I think doing the ACF integration will work better. Thank you for your tutorial.

    • The form_id_is passed as a parameter to the frm_after_create_entry action. Using the form_id, you can either use a a series of if statements or a switch statement to include multiple forms in a single script.

  5. Thanks great work, but i need some help 🙂

    The first time i submit my form is working like a charm.

    But what i need is to update, add, delete data in the repeater with the option “Allow front-end editing of entries” via the same form.

    So, when i add, update, delete new data in my form and i submit, the “wp_postmeta” table is filled by data and my “entries” in formidable form too but not the repeater in my custom post type.

    any idea ?

    Cheers

  6. Hello and thank you for this post
    I am very new at all these code and finding it a bit difficult navigating it.

    I have a wordpress install locally and ive created a CPT and a formidable form with the same details as stated in the post. But when i submit, a CPT post is created as intended but without the repeater elements. Kindly let me know how to get it to work as i feel there are some part of the code that i have to further change like the Form ID. If i’m right please help me out or point me in the right direction

    Thank you