ACF - How To Display All Fields In A Field Group

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.

About

Web Developer

References   [ + ]

1. "DRY" = "Don't Repeat Yourself".
2. You can see this in the URL when editing a field group.

11 Comments

  1. Bree

    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?

    1. David

      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:

      <?php
      $checkbox_values = get_field('checkbox_values');
      
      if( $checkbox_values ): ?>
      <ul>
      	<?php foreach( $checkbox_values as $value ): ?>
      		<li><?php echo $value; ?></li>
      	<?php endforeach; ?>
      </ul>
      <?php endif; ?>
  2. Jansie

    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.

  3. alex

    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’?

    1. David

      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!

      1. alex

        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

    1. David

      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 to WP_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,

      		if ( $field_value && !empty( $field_value ) ) {
      			$specifications_fields[$field['name']] = $field;
      			$specifications_fields[$field['name']]['value'] = $field_value['display_name'];  // You could also use keys like ID, user_firstname, etc.
      		}
      

      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 original get_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.

          <div class="col-xl-9 col-lg-8 col-md-8 col-sm-6 col-xs-12 value">
              <?php if ( $field['type'] === 'user' ) : ?>
                  <!-- Again, you can use any of the keys provided by the return value, like ID, user_firstname, etc. //-->
                  <?php echo $value['display_name']; ?> 
              <?php else : ?>
                  <?php echo $value; ?>
              <?php endif; ?>
          </div> 
      

      In this example, you could also conditionally check the field $name or any of the other data keys being returned. Just debug out what your get_specifications_fields function returns, using print_r().

    1. David

      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:

      <h1><?php echo get_the_title( 479 ); ?></h1>

      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:

      <?php
      function get_specifications_fields() {
      
          global $post;	
      
          $specifications_groups = array( 479, 480, 481 ); // Post IDs of the specifications field groups.
          $specifications_fields = array();
      	
          foreach ( $specifications_groups as $group_post_id ) {
              $fields = acf_get_fields( $group_post_id );
      
              // Prefix field name with the group post ID to prevent key conflicts
              $field_group_key = $group_post_id.'-'.$field['name'];
      	
              foreach ( $fields as $field ) {
                  $field_value = get_field( $field['name'] );
      		
                  if ( $field_value && !empty( $field_value ) ) {
                      $specifications_fields[$field_group_key] = $field;
                      $specifications_fields[$field_group_key]['value'] = $field_value;
                  }
              }
          }	
      	
          return $specifications_fields;
      
      }
      

      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.

Add Your Thoughts

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