If you need to pull custom field data from a lot of WordPress posts, get_post_meta outperforms ACF's get_field significantly.

If you’ve ever used the Advanced Custom Fields plugin to pull custom data from a WordPress database, you know how fantastically easy the get_field() function is to use. But I recently found out it’s also fantastically easy to abuse. Sometimes it’s better to use get_post_meta().

In my page template, I began with a standard get_posts() query like this…

<?php
 $posts = get_posts(array(
 'numberposts' => -1,
 'post_status' => 'publish',
 'post_type' => 'places',
 'orderby' => 'title',
 'order' => 'ASC'
 ));
?>

This fetches all published posts from a Custom Post Type I’d set up called ‘places’, and orders them alphabetically by their titles.

I then wanted to iterate through the posts and summarize their contents on screen in an unordered list populated with standard data like Title and Permalink, but also with data from custom fields.

ACF to the rescue, right? Just use get_field() — it’s so handy!

Here’s my first pass at the code…

<?php
if($posts) {
 echo "<ul class=\"className\">";
 foreach($posts as $post) {
   echo "<li>";
   echo '<strong><a href="'.get_permalink().'">'.get_the_title().'</a></strong><br>';
   echo "Address: ".get_field('street_address')."<br>";
   echo "Phone: ".get_field('phone_number');
   echo "</li>";
  }
 echo "</ul>";
}
?>

The problem? The page took so long to load, it actually timed-out. Not only was this delay a total deal-breaker but the resulting error broke the page layout, leaving users in the lurch.

It took me a while to realize what was going on.

The get_field() function works really well when you want to pull data from a few fields and display them on screen via a template. For example, it’s great when you need to display custom field data from a single post — the overhead of going and fetching that data, even a few dozen times, won’t slow down WordPress in a noticeable way.

However, if you’re iterating through a large set of records, perhaps using get_field() hundreds of times, the time spent sending WordPress back to the database to run hundreds of distinct queries really adds up.

Speeding things up with get_post_meta()

I realized I already had all the data I needed because all data from posts is retrieved during a get_posts() query, including all the custom fields. Instead of using get_field(), I simply switched to using WordPress’ built-in get_post_meta() function.

Calls like get_field('street_address') become get_post_meta( get_the_ID(), 'street_address', true ), resulting in my second pass…

<?php
if($posts) {
 echo "<ul class=\"className\">";
 foreach($posts as $post) {
   echo "<li>";
   echo '<strong><a href="'.get_permalink().'">'.get_the_title().'</a></strong><br>';
   echo "Address: ".get_post_meta( get_the_ID(), 'street_address', true )."<br>";
   echo "Phone: ".get_post_meta( get_the_ID(), 'phone_number', true );
   echo "</li>";
 }
 echo "</ul>";
}
?>

The result: no extraneous calls to the database, and WordPress now delivers the page instantly to users.

What I learned about WordPress and get_post_meta()

This may be stating the obvious but, if you need to pull data from a lot of posts at once, get_post_meta() outperforms get_field() significantly.

Leave a Reply

‹ Back to Latest Articles