Desert road
Advanced Custom Fields (ACF) is an amazing plugin that can revolutionize the way you build and edit posts inside WordPress. Two of the more common ACF features are repeater fields and flexible content fields, which can make the post editing experience much more intuitive. In fact, I can’t recall the last website I build where I did not use ACF repeater or flexible content fields.

ACF is great, but…

There are a couple of things about ACF that leave something to be desired, one of which is the function get_field(). This function is extremely convenient when working with repeater and flexible content fields because it retrieves all of the pertinent meta values and puts them into a nice multidimensional array; however, it is also expensive when it comes to performance.

In a classic post by Bill Erickson, he recommended not using ACF functions like get_field() largely because of poor performance. Bill recommends using the native WordPress function get_post_meta() to retrieve post meta values because it’s faster and won’t result in the dreaded white screen of death that could happen if/when ACF is deactivated.  Craig Simpson also did a nice writeup about performance considerations when working with ACF, along with the numbers to prove it.

WET Code Stinks

Now there’s a slight problem with using get_post_meta() vs. get_field(): it can be a bit of a pain to write the functions that retrieve the post meta values for all those repeater subfields and flexible content layouts.

What’s worse is that because these ACF field groups are often tailored for each client, you usually end up rewriting these functions on every project. And WET (Written Every Time) code is something that no developer is proud of.

Is There a Better Way?

In a recent project I challenged myself to find a better way to get the ACF post meta values.  I was hoping to come up with a function that could be called once and return a multidimensional array with all the meta values that I needed. In essence, I was looking for a direct replacement for get_field().

This is the recursive function that I came up with:

 

How to Implement get_all_custom_field_meta()

The function get_all_custom_field_meta() has two required parameters: the post ID, and a config array. The config array must have the same structure as the ACF code for exporting/importing field groups.

UPDATE: I recently learned of ACF Pro’s Local JSON feature, which automatically saves the latest version of your field group configuration into a folder in your theme. The manual approach below still works, but my preference is the automated way.

1) Manual way: Copy the fields array from ACF’s field group export or condense it down like this. Either will work.

ACF export fields groupACF field group export code

2) Automated way: Once you set up ACF Pro’s Local JSON feature you never have to remember to update the config. Just include the entire field group configuration JSON (which is always the latest verstion), decode it to an array, and pass the array to get_all_custom_field_meta(). This is what it looks like:

And here is an example array that is returned by calling get_all_custom_field_meta( get_the_ID(), $config ):

Hurray for DRY Code!

Yes, I think there is a better way than relying on get_field() or continually rewriting functions to retrieve ACF repeater and flexible content field values. The function get_all_custom_field_meta() is flexible, meaning your code stays DRY (Don’t Repeat Yourself), plus it returns all of the post meta values in a nice multidimensional array.

Oh, and it’s fast too. I ran some basic performance tests and get_all_custom_field_meta() was 50-100 times faster than get_field() in the example provided here (and 300+ times faster in other tests that I ran). The relative performance gap widens (gets better) as the config array increases in complexity because the function is doing far less work than get_field().

Give it a whirl!

Reader Interactions

Comments

  1. Thank you for posting this Tim. As a newbie developer (following along on KnowTheCode.io), I’m going to bookmark this post and refer back to it when I get to the point in my learning when I start learning about `post_meta` and `get_post_meta`. I’ve seen/read complaints by others about the poor performance of ACF’s extended functionality. Up until now, I’ve not seen an alternative work around that relies on PHP and the WordPress API.

    • You’re welcome, Robert. ACF functions are extremely powerful and convenient but they do come at a cost, as you know. Hopefully this code will come in handy for you at some point.

  2. Hello, could you clarify if this method still applies for ACF 5 ? I know there were many integrations but I didn’t see in your article what version this testing is done on. Thanks for your post!

    • Hi Kurt, thanks for your comment. I have tested this approach with ACF Pro version 5+ and it works great. Let me know how it goes for you.

  3. Just looped back around to see you’ve updated to use ACF-JSON, this a GREAT addition! The biggest downfall of this was updating the config as things changed, but now there is no need. Super useful man, thanks again!

    • Thanks, Mike. I’m sure you’ll find ways to make it even more useful, so feel free to contribute!

  4. Great Tutorial and works great. I’m wondering, if there’s a way to set the field_group_json globally so that I don’t have to add it to every template that I’m using. I’m using the underscore theme and if I want to access global variables in the template parts, it doesn’t work.
    Any Idea?

  5. Hi Tim & thanks for this! I’m excited to get it working. Unfortunately I’m getting an error when I try to call the function:

    Catchable fatal error: Argument 1 passed to TimJensen\ACF\Field_Group_Values::get_field_value() must be an instance of TimJensen\ACF\string, string given, called in C:\Users\Michelle\Documents\Websites\sitename.dev\wp-content\plugins\acf-field-group-values-master\src\Field_Group_Values.php on line 78 and defined in C:\Users\Michelle\Documents\Websites\sitename.dev\wp-content\plugins\acf-field-group-values-master\src\Field_Group_Values.php on line 155

    Using get_field() for this same field works correctly (it’s a WYSIWYG field). The $config array is being generated correctly – I used the local JSON method. Any ideas of what could be causing this?

    thanks! Michelle

  6. Hi again Tim – just moved to PHP 7 and downloaded the latest version, thanks! I’m now trying to get this working on fields saved to taxonomy term pages. I am able to retrieve values using the usual taxonomy+ID method of passing the faux “post ID” for taxonomy terms, ie:

    get_field(‘color’, ‘category_17’);

    Which gives me a #hexvalue. But when I try passing ‘category_17’ as the postID here:

    $acf_post_meta = get_all_custom_field_meta( $postID, $config);
    var_dump($acf_post_meta);

    I get an array with 1 element, color => false. I’ve confimed my $config is pulling everything from the taxonomy JSON.

    Any ideas? Thanks!

    • Hi Michelle,

      I haven’t built support for taxonomy terms, but thanks for the idea!

      Honestly, unless you’re using repeater or flexible content fields it might be simpler to use get_term_meta(). I only use get_all_custom_field_meta() when working with more complex fields (repeater/flex).

    • Hi Michelle,

      I’ve just updated the plugin to version 2.1.0 with support for term meta. You will need to supply the term ID in the form of ‘term_17’. I hope this helps!

Leave a Reply

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