Why Using ACF’s get_field() is a bad idea
Why Using ACF’s get_field() is a bad idea
As a WordPress developer, efficiency and performance are always at the forefront of my mind. One tool I frequently use is Advanced Custom Fields (ACF), which allows for extensive customization and management of custom fields. However, when it comes to fetching these fields in my templates, I've learned that not all methods are created equal. Specifically, I've found that avoiding ACF's get_field()
function in favor of get_fields()
can significantly improve performance. Here’s why.
The Problem with get_field()
get_field()
is a handy function provided by ACF to retrieve the value of a specific custom field. It's straightforward and intuitive:
$value = get_field('my_field');
However, in a typical ACF-heavy WordPress project, you often need to retrieve multiple custom fields within a single page or block. If you use get_field()
repeatedly, each call makes a separate query to the database. For example, if you have ten custom fields and you call get_field()
for each one, you're making ten separate database queries.
Here's an example snippet:
$background = get_field('background');
$accent = get_field('accent');
$text_color = get_field('text_color');
$title = get_field('title');
// ... and so on
While each individual query is fast, the cumulative effect can slow down your page load time, especially on pages with many custom fields or when your site experiences high traffic.
The Better Alternative: get_fields()
To mitigate this, I use get_fields()
instead. This function retrieves all custom fields for a given post in a single query, returning them as an associative array. This approach significantly reduces the number of database calls:
$fields = get_fields();
$background = $fields['background'];
$accent = $fields['accent'];
$text_color = $fields['text_color'];
$title = $fields['title'];
By fetching all the fields at once, get_fields()
minimizes database load and improves overall site performance. This is particularly beneficial for pages with multiple ACF blocks or complex field groups.
Real-World Example
Let’s look at a concrete example from a recent project. I was working on a series of custom Gutenberg blocks, each with multiple ACF fields. Initially, I used get_field()
within each block, like this:
$background = get_field('background');
$accent = get_field('accent');
$text_color = get_field('text_color');
$title = get_field('title');
$content = get_field('content');
This approach was functional but resulted in numerous database queries. To optimise, I switched to using get_fields()
at the start of the block rendering process:
$fields = get_fields();
$args = array(
'background' => $fields['background'] ?? 'var(--color5)',
'accent' => $fields['accent'],
'text_color' => $fields['text_color'] ?? 'var(--color6)',
'title' => str_replace(['<p>', '</p>'], '', $fields['title'] ?? ''),
'content' => $fields['content'],
'max_width' => $fields['max_width'] ?? '100%',
);
This single call to get_fields()
reduced the number of database queries from multiple to one. The performance improvement was noticeable, with faster page load times and a smoother user experience.
Caching with Transients
For even greater performance gains, especially on high-traffic sites or pages that don't change frequently, you can cache the result of get_fields()
using transients. This is even faster than calling get_fields(), as the data requires less computation :
$cache_key = 'acf_fields_' . get_the_ID();
$fields = get_transient($cache_key);
if ($fields === false) {
$fields = get_fields();
set_transient($cache_key, $fields, HOUR_IN_SECONDS); // Cache for 1 hour
}
While it’s true that retrieving a transient still involves a database call, it’s more performant for several reasons:
- Reduced Database Load: Transients are stored in the options table, which is optimised for quick retrieval. Fetching a single option (the transient) is faster than multiple queries for each custom field.
- Fewer Queries Over Time: By caching the fields for an hour (or any suitable duration), you avoid multiple queries on subsequent page loads, reducing the overall database load.
- Consistent Performance: Even though the transient itself is fetched from the database, it consolidates the data retrieval into a single, quick operation, resulting in more consistent performance.
Conclusion
While ACF’s get_field()
function is convenient for fetching individual custom fields, its repeated use can lead to performance issues due to multiple database queries. By switching to get_fields()
to retrieve all fields in a single query, and optionally caching the results with transients, you can significantly improve your WordPress site's performance.
This approach has become a standard practice in my development workflow, ensuring that my sites run efficiently even as they grow in complexity. So next time you’re working with ACF, consider ditching get_field()
in favor of the more performant get_fields()
. Your users—and your server—will thank you.
Categories:
General |