Updates to ACF Field Functions in 5.11
In versions of ACF prior to 5.11, the ACF shortcode [acf field="field_name"]
, along with the get_field()
and the_field()
functions, could also be used to retrieve WordPress options or post, user or term meta values which weren’t ACF fields. Depending how these functions were used, it could have security implications as site options could inadvertently be exposed to the frontend or to users who do not have admin permissions. In addition, these functions could retrieve values of fields that are no longer registered with ACF, as their meta values remain in the database.
Aside from being a security risk, we don’t recommend using functions like get_field()
to get anything other than an ACF field. These functions run additional logic and database queries to find a valid field and format it correctly. As a result it would be less performant to use get_field
instead of the relevant WordPress core functions.
With ACF 5.11.2 and above, the ACF shortcode will only retrieve values for registered ACF fields, whilst get_field()
and the_field()
will prevent access to site options which are not registered ACF fields. While this should be fine for most sites, there are a few scenarios that might require special attention. This doc will go over some of those scenarios and offer some solutions.
For ACF 5.11 and 5.11.1, the data access changes for the ACF shortcode were also applied to get_field()
and the_field()
.
Using ACF Functions to Retrieve Data From Outside ACF
The update to ACF version 5.11.2 means that calling the ACF shortcode on non-ACF options or post, user or term meta will return null, whereas before it might have returned the value.
Calls to get_field() or the_field() on non-ACF WordPress options will also return null. However, using those functions to retrieve any post, user or term meta will return the value, regardless of if the meta is an ACF field.
To avoid this, we recommend using WordPress core functions to retrieve non-ACF field data. Developers should use the get_option()
function to retrieve data in the wp_options
table, or the get_post_meta()
function to retrieve meta from the wp_postmeta
table.
In ACF 5.12.1, these restrictions now also correctly apply when using a field key to access an option value, the same as using the field name.
Registering Fields via PHP
Any fields registered using the acf_add_local_field_group() and acf_add_local_field() PHP functions should be registered before get_field()
is used. We recommend registering any local fields on the acf/init action hook or directly in your theme’s functions.php
file.
It’s important to note that calling get_field()
or the_field()
will initialize ACF if it hasn’t done so already. This means that if you call those functions before your local field groups are registered, ACF won’t be able to find those fields.
Starting with 5.11.1, ACF will detect if this has happened, and output a _doing_it_wrong
notice to your PHP error log. From 5.11.2, we will still return data along side this warning to avoid site errors while you modify your code to be compatible.
To correct this, make sure that:
- Field groups registered via PHP are registered after ACF has initialized, preferably on the
acf/init
hook. - Calls to
get_field()
orthe_field()
happen inside an action hook/filter which fires after your fields have been registered, or inside your theme’s template files.
Below is an example of how to correctly register fields using the acf/init
hook.
add_action( 'acf/init', 'my_acf_add_local_field_groups' );
function my_acf_add_local_field_groups() {
acf_add_local_field_group(array(
'key' => 'group_1',
'title' => 'Page Hero',
'fields' => array (
array (
'key' => 'field_1',
'label' => 'Hero Title',
'name' => hero_title,
'type' => 'text',
)
),
'location' => array (
array (
array (
'param' => 'post_type',
'operator' => '==',
'value' => page,
),
),
),
));
}
Registering Fields Inside Conditional Logic
Care should be taken when registering local fields/field groups inside conditional logic, as get_field()
and related functions may not work as intended.
For example, the following code registers a field in PHP, but only in the WordPress admin due to the is_admin()
check. Any calls to get_field()
in frontend theme code wouldn’t be able to retrieve the value for that field:
if ( is_admin() ) {
add_action( 'acf/init', 'my_acf_add_local_field_groups' );
}
function my_acf_add_local_field_groups() {
acf_add_local_field_group(array(
'key' => 'group_1',
'title' => 'Page Hero',
'fields' => array (
array (
'key' => 'field_1',
'label' => 'Hero Title',
'name' => hero_title,
'type' => 'text',
)
),
'location' => array (
array (
array (
'param' => 'post_type',
'operator' => '==',
'value' => page,
),
),
),
));
}
The conditional logic needs to be removed so that the ‘acf/init’ action is called on both the admin and frontend of the site:
add_action( 'acf/init', 'my_acf_add_local_field_groups' );
Multisite Installs Using the Same Field Across Multiple Subsites
ACF fields are only available to the subsite that registered them. If you want to use the same ACF field on multiple subsites, you should create the field on any subsites that will use the field.
Alternatively, you could export the field groups that you want to re-use as PHP (via Custom Fields -> Tools -> Generate PHP), and include that PHP in the functions.php
file of any themes used by the subsites. This will register the fields via PHP, and make sure they are available across the multisite network.