As a WordPress developer, I create a lot of custom data to give clients the functionality they want. I’ve used every way possible, like posts for a custom post type, post meta, taxonomies, options, custom tables, etc. However, for ease of use and client convenience, I mostly use either WordPress native custom fields or the Advanced Custom Fields PRO plugin. With ACF, the interface is great, and, having used it so much, I can quickly setup any field type very quickly. The most time consuming part of using custom data is when it comes time to integrate into the theme.
For Example
One use case I keep encountering is displaying separate fields in a single list. Think of product product specifications. We might have fields like UPC, Length, Weight, Material, Pages, and so on. If we’re using a plugin like ACF, our specifications fields might use various field types may vary as well. However, I like to give specifications their own field group, separating them from content that may be displayed more free-form on the public side.
With predictable display characteristics on the front end, we can setup a UL
to display the values of the specs. However, we have to know the field name for each specification we want to display and call the_field
to spit it out. Needless to say, if we have a ton of specification fields, we’ll be violating the “DRY”1”DRY” = “Don’t Repeat Yourself”. best practice as a developer. It would be nice if we could condense the code for getting and displaying our fields.
Get All Field Group Fields
It turns out that, with a bit of custom code and a function provided by ACF, we can elegantly solve our predicament. The solution I’m providing here only works with ACF, but could be modified to work with standard post meta or posts of a custom post type in WordPress. We’ll start by getting the fields and aggregating them.
The following assumes you have created fields in a field group using ACF. Open up your theme’s functions.php file, and add the following:
<?php
function get_specifications_fields() {
global $post;
$specifications_group_id = 479; // Post ID of the specifications field group.
$specifications_fields = array();
$fields = acf_get_fields( $specifications_group_id );
foreach ( $fields as $field ) {
$field_value = get_field( $field['name'] );
if ( $field_value && !empty( $field_value ) ) {
$specifications_fields[$field['name']] = $field;
$specifications_fields[$field['name']]['value'] = $field_value;
}
}
return $specifications_fields;
}
This function get all fields for a given field group using the acf_get_fields
function from ACF. The only variable is on line 5, which will hold the field group ID.2You can see this in the URL when editing a field group. While looping through all the fields in the group, we check for a value. If a field has no value, we ignore it. Fields with valid values are stored in a separate array that is eventually returned.
Now we need to use this code to display our specifications in the theme. Pick a place to display the data, and use something like this:
<div class="row">
<?php
$specifications_fields = get_specifications_fields();
foreach ( $specifications_fields as $name => $field ):
$value = $field['value'];
?>
<div class="col-xl-3 col-lg-4 col-md-4 col-sm-6 col-xs-12 key">
<strong><?php echo $field['label']; ?>:</strong>
</div>
<div class="col-xl-9 col-lg-8 col-md-8 col-sm-6 col-xs-12 value">
<?php echo $value; ?>
</div>
<?php endforeach; ?>
</div>
For simplicity, I’m using some Bootstrap classes to help style our specs as a list. The rest of the code is pretty straightforward. We’re calling our get_specifications_fields
function and looping through the results.
Other Possibilities
Although this example is very simple, it illustrates how to condense repetitive code. I’ve used this code in custom plugins. I usually add filters for the field data at various points to exclude fields and alter the results. I also have code to do certain things based on a specific field’s type. For instance, a true-false field may be converted to a “Yes” or “No” when returned.
Finally, when I use this code in a plugin, I usually create a shortcode for the admin/editor use inside their main content, whether that’s the_content
, a page builder, ACF Flexible Content, or tons of other places. With the right UI, the user can select which field group to use and the ID is passed as a parameter to the shortcode. The downside of using this as a plugin is that the structure/styling of the output is a little less accessible because it’s no longer part of the theme. However, we deal with that all the time for many other WordPress plugins.
This is awesome, thank you. Can you tell me how you might echo values from something like a checkbox when it may be outputting an array?
You’re welcome. If you had a checkbox with multiple selected values, you would just loop through the array provided by
get_field
, like so:I use this code and its very useful but i have some question.
1-how to add commas in this code.
2-its make a url which is good, if i got space in text, it shows %20 in url. So how to convert this %20 into dash (-).
3-url give capital word if i use capital word, is it possible that it will automatically creat small alphabets in url?
Thanks again for your help.
rawurldecode
thestr_replace
the decoded spaces with dashes. Be sure tofilter_var
and sanitize your URLsstrtolower
function to lowercase the entire stringHope this helps!
Thank you a hundred times over. I modified your code to suit one of my applications and it works a charm.
I asked at the ACF forum and I’m still hearing crickets, so this is a site-saver.
So chuffed. Thanks again.
Glad it helped you out!
Thanks a lot for this,
how about if the field group contain a bunch of repeater fields?
Any way we can output the single values rather than ‘Array’?
You’re welcome!
In the case of a “repeater” field type inside the group, you could refactor the code to get the individual child fields of the parent. So, the
get_specifications_fields
function would accept the post ID of the field group as an argument, and it would just return an array. Another function would flatten the resultant fields into your returned array.I’ll post a proof of concept soon!
Hi David,
Any chance you might have sample code to get this working with repeaters?
I’ve been unable to do so and going crazy!
Cheers
What if user field type is used, and it returns an array instead of a value?
When using the “User” relationship field type, the “value” result from calling
acf_get_fields
will be an array. The structure depends on whether or not you allow multiple users to be selected for the field. In either case, the end value for the user is an array contains data similar toWP_User
.Using the example code above, you have a couple of options. Depending on what data you need to display for the user, you might flatten the returned data include only what you need. For example,
However, this edit would only work for user field types and breaks functionality for others. I would actually return the original value in your
$specifications_fields
array, leaving the originalget_specifications_fields
function unchanged.Instead, you could just change what is displayed in the theme. Looking at the example theme code above, you could check the field type, and display the correct “value” accordingly.
In this example, you could also conditionally check the field
$name
or any of the other data keys being returned. Just debug out what yourget_specifications_fields
function returns, usingprint_r()
.How can I show a field group title, and how can I show multiple field groups, not only one?
In ACF, field groups are actually just posts with a post type of “acf-field-group.” Using the post ID of a field group, you can just call WordPress’s
get_the_title
function. Example:If you need to show multiple lists using multiple field groups, you can refactor the above code to use an array of post IDs. You can do this in many different ways, but here’s one example:
This code just loops through a list of ACF field group post IDs. Another change is the key for each field is now prefixed by the current iteration’s group post ID. This will prevent conflicts when two fields in separate groups have the same name.
Hi, how do I display a group of fields related to the current term/taxonomy of the page?
I tried:
global $wpdb;
$specifications_group_id = $term_id;
but it did not work
Moses,
The fields are grouped under the field group ID not the term ID of the taxonomy. Try using the post ID of the field group instead.
Was there ever a sample posted with how to loop through repeaters? My text fields show up fine but I’m having a hard time drilling down into sub-fields. It just says “array”.
Here are a few suggestions on how to handle the Repeater field type. I’ve componentized a few functions for reusability and nestability. You’ll want to add this after the
get_specifications_fields
function which remains unchanged.This code is only a demonstration for Repeater subfield types of ‘repeater’, ‘image’, and ‘text’. It will have to be customized to work with your specific subfields by adding new switch cases inside the
output_specification_array
function.In your theme template file where you want to output the markup created by these functions, you can simply replace the code referenced in the tutorial with:
Hope this helps!
Thanks you!
This code just loops through a list of ACF field group post IDs. Another change is the key for each field is now prefixed by the current iteration’s group post ID. This will prevent conflicts when two fields in separate groups have the same name.
Yes, if you have two field groups with the name name, you can concatenate the name with the ID to ensure they are unique. Example:
Hello,
You saved me a lot of time. I tried to modify your code but it’s not work.
I have 3 group of custom field: Group A, Group B, Group C. I tried to get the values each groups to separated array like $group1[value], $group2[value] and $group3[value].
Can you give me an example?
Thanks
I would just grab all three field groups and concatenate them into one array with the group being a disparate key. So, something like:
Then, you can loop through them in a similar fashion as described in the post, but you’ll have to add another, higher-level loop.
Can you help me with full of codes? I tried but got a lot of troubles with print value per groups.
For more assistance, feel free to contact me directly or propose a project on Upwork.
Hi, thank you. It’s the only thing close to what I need that I could find. I wonder is there away to do this with also data from a specific page. I have a contact page with two groups of fields. One with social links and one with address info. I want to group all the information from the address field from the contact page to place on the footer of each page. The code example looks like its for dynamic pages, i.e. page.php or whatever. But I just want the data from one group from one specific page. So I’m trying to figure out how to tell it to include $page_id
You can pass the second parameter to the
get_field
function, which is the$post_id
. See https://www.advancedcustomfields.com/resources/get_field/Thank you for this tutorial. I’m trying it in Oxygen Builder and putting everything inside the code block. But it doesn’t work 🙁 Even when I use only part of the code and checking the functionality with echo or print_r I’m not able to see values.
I’m trying to put the echo here
foreach ( $specifications_fields as $name => $field ):
$value = $field[‘value’];
echo $field;
?>
nothing is displayed
The issue with this code is that you’re trying to echo out an array. I think this should read `echo $value;`.