tl;dr You can get all the fields stored in Advanced Custom Field with:
$groups = apply_filters( 'acf/get_field_groups', array() ); if ( is_array( $groups ) ) { foreach ( $groups as $group ) { $fields = apply_filters( 'acf/field_group/get_fields', array(), $group['id'] ); return $fields; } }
For my The Events Calendar Shortcode Pro plugin, I wanted to add the ability to filter by a field added with Advanced Custom Fields. This way with a field named additional_data someone could use the following shortcode to only list events with the value “Test Data” in that field:
[ecs-list-events additional_data="Test Data"]
So I started looking for documentation on getting all field groups from Advanced Custom Fields and then getting all the fields in each group, but the documentation for getting the groups was a bit thin.
I thought you could do something like:
$groups = get_field_groups();
But Advanced Custom Field actually hides this function within a class:
class acf_field_group { var $settings; /* * __construct * * @description: * @since 3.1.8 * @created: 23/06/12 */ function __construct() { // actions add_action('admin_enqueue_scripts', array($this,'admin_enqueue_scripts')); // filters add_filter('acf/get_field_groups', array($this, 'get_field_groups'), 1, 1); add_filter('acf/field_group/get_fields', array($this, 'get_fields'), 5, 2); // ... } function get_field_groups( $array ) { // cache $found = false; $cache = wp_cache_get( 'field_groups', 'acf', false, $found ); if( $found ) { return $cache; } // get acf's $posts = get_posts(array( 'numberposts' => -1, 'post_type' => 'acf', 'orderby' => 'menu_order title', 'order' => 'asc', 'suppress_filters' => false, )); // populate acfs if( $posts ){ foreach( $posts as $post ){ $array[] = array( 'id' => $post->ID, 'title' => $post->post_title, 'menu_order' => $post->menu_order, ); }} // set cache wp_cache_set( 'field_groups', $array, 'acf' ); return $array; } // ... } new acf_field_group();
We can’t just call the get_field_groups function directly because the instance of the acf_field_group class isn’t available to us. We could create another instance with
new acf_field_group()
somewhere in our code, but then we have two copies of the class running for no reason (and might mess things up with the filters being registered twice).
Unlike a normal filter which would take some data and either return it back or modify it, the get_field_groups function is ignoring the input value of $array and just returning the data for the field groups no matter what.
So you’re actually applying a filter to fetch the data, which isn’t really filtering anything:
$groups = apply_filters( 'acf/get_field_groups', array() );
Whereas normally the data would be fetched first into $groups and then apply_filters called so others can modify it, ie.:
$groups = ... some code to get the groups data ...; $groups = apply_filters( 'acf/get_field_groups', $groups );
We can still hook into the acf/get_field_groups filter and modify the field groups after get_field_groups provides it, but the initial data isn’t available before the acf/get_field_groups filter is initially run.
Interesting usage of WordPress filters and not something I’ve seen done before!