Appending Custom Data To Post Title For The ACF “Post Object” Field Type

Working on a WordPress project gives the the opportunity to tinker and learn.  On a project I completed recently, we used a few custom fields, courtesy of Advanced Custom Fields PRO.  Although I loathe the “do it with a plugin”-first mentality, ACF is a mu-plugin1Must-Use Plugin.  In other words, something that lessens the likelihood of someone else screwing things up. for nearly every site I work on.  It grants the user a ton of content flexibility when setup properly, but it also offers me, the developer, ways to easily alter its function without editing the plugin itself.  That’s exactly what I did when I received a common ACF request while working on the aforementioned project.  I want to share the experience(and the code) to both illustrate my point and, hopefully, save someone else a little time.

The “Post Object” Field Type

One ACF field type I use a lot is Post Object.  With it, users can quickly point to other posts when adding/editing content.  By far, the biggest use for this field type on the front end is when creating a “related” section.  Wrap the field in a “Repeater”, and internal linking between various posts, pages, and custom post types becomes quick and easy.  There are settings to limit which posts are available for choosing, like filtering by post types or taxonomies, and you can choose to return either a full post object or just a post ID when using get_field in the theme.

More Posts, More Problems

ACF Post Object - Duplicate Posts

Posts with similar titles are hard to distinguish in the dropdown.

I have, however, been asked a few times if it is possible to display additional text related to a specific post for each option in the Post Object field type.  In other words, instead of just showing up in the select as “Post Title”, we add extra, defined text to produce something like “Post Title (Extra Text)”.  The request may seem odd, but there are actually a few good reasons for needing such a feature.

A common reason is to eliminate ambiguity when posts share similar post titles.  For example, you have a WooCommerce site with a lot of products.  You have a product that is sourced from two different vendors.  Although the items have different post IDs, they share the same name(post title).  How is the user to know which is which when selecting from the Post Object options?2This is really a bad example, but it illustrates my point.  In this case, the proper way to handle one product with multiple vendors is to change from a one-to-one relationship to a one-to-many relationship.  There are a couple of ways to deal with such a scenario.

“There has to be a better way!”

The ugly fix is to simply edit the post title for each product with some additional text that allows any editor to distinguish between products sharing the same name.  This isn’t optimal because it changes a product’s name across the entire site. The extra text, which is intended to be used only internally, now shows up everywhere. Yuck.

It’s much better to change only how the values are displayed in the dropdown on the edit post page.  Doing it this way requires some coding, but leaves our current titles intact, and the user side of the site is also unaffected. The code is fairly simple; it’s just a matter of knowing the right ACF hook to use.3For version 4.1.2 and later.

Extending ACF

The filter we’re interested in is acf/fields/post_object/result.  This hook allows us to alter results in the ACF function get_post_title.  Looking at the documentation for this filter, we see there are four arguments that are passed to us: $title$post$field, and $post_id.  In particular, we’ll be using the $title argument to add our extra text to each post title and the $post object for our appended text.

With the ACF filter, we can easily suffix post data to each selection in the “Post Object” field type.  The most basic, yet unique, data we can tack on to the post title is the post ID.  It’s provided to us as part of the $post object, which is the second argument of the acf/fields/post_object/result hook. To append the post ID, we can use the following code in our theme’s functions.php file:

<?php
function update_acf_post_object_field_choices($title, $post, $field, $post_id) {
	$title .= ' [' . $post->ID .  ']';
	
        return $title;	
}

add_filter( 'acf/fields/post_object/result', 'update_acf_post_object_field_choices', 10, 4 );
?>

Pretty simple, right? We’re just adding a filter to be run when acf/fields/post_object/result is applied to each post in the resultant dropdown. So, what does it end up looking like for the user?

ACF Post Object with Post ID Added

The post ID has been added in brackets for each option in the select.

Going Further with ACF Data

Our suffix filter works great, and we could stop here.  However, a post ID may not mean much to your regular WordPress user, so we need to find something a little more descriptive and meaningful to use as our post title suffix.

When working with products, we might use data like UPC, ISBN, etc. Going back to my example from earlier, we could use a field that indicates the vendor or supplier. The problem is that these are custom fields and aren’t available in the $post object.

For the purpose of this tutorial, I’ve setup a “SKU” ACF that is a simple “Text” field type, and we’re going to add that to each post title.  We just need to tweak our code slightly to grab an ACF’s value.

<?php
function update_acf_post_object_field_choices($title, $post, $field, $post_id) {
    $sku_value = get_field('sku', $post->ID);
   
    if ( $sku_value && !empty($sku_value) )	{
        $title .= ' [' . $sku_value .  ']';
    }
	
      return $title;	
}

add_filter( 'acf/fields/post_object/result', 'update_acf_post_object_field_choices', 10, 4 );
?>

We’ve changed $post->ID to get_field('sku', $post->ID). Since we’re using this code outside the usual post loop, we need to pass the relevant post ID to ACF’s get_field method as the second parameter.

ACF "Post Object" Custom ACF Value Suffix

Appending an ACF value to the post title for each option in the “Post Object” field type.

After updating our code, the posts dropdown now includes a SKU after the post title. Now that we have functioning code, we could format the custom data differently, like using a dash instead of brackets or parentheses, or the post title could be eliminated completely, if the ACF value means more to editors.

We could also add the custom field’s label, “SKU”, by changing:

$title .= ' [' . $sku_value .  ']';

To:

$title .= ' [SKU: ' . $sku_value .  ']';

You’re not limited to simple text field values either. For field types like “Repeater”, multi-select, taxonomies, etc., the custom field values come in the form of arrays, so the code would be slightly more complex. Imploding the values and separating them with commas would be trivial. If you need to limit the number of values, format them, or do something else that requires a “walk”, it’s not too much more trouble.

You could also turn this in to a simple plugin with some settings, like I have. In the plugin’s settings page, the user can choose whether to enable the add-on, the meta field to append to each post title, and how to format the added text.4I’ll be making the plugin available soon.

In the meantime, to use the example code from above, you need only to put the code inside your theme’s functions.php file and customize it to fit your needs. Be sure to include the add_filter line and ensure that either the free or “PRO” version of Advanced Custom Fields is installed and activated.5Virtually all WordPress sites I work on require ACF. My suggestion is to either make ACF a “mu-” plugin or do a is_plugin_active check. Also be sure to use the correct ACF field name for the data you want to add to the post title.

If you do use the code above or have suggestions on how to improve or extend it, please let me know!

About

Web Developer

References

References
 1 Must-Use Plugin.  In other words, something that lessens the likelihood of someone else screwing things up.
 2 This is really a bad example, but it illustrates my point.  In this case, the proper way to handle one product with multiple vendors is to change from a one-to-one relationship to a one-to-many relationship.
 3 For version 4.1.2 and later.
 4 I’ll be making the plugin available soon.
 5 Virtually all WordPress sites I work on require ACF. My suggestion is to either make ACF a “mu-” plugin or do a is_plugin_active check.

6 Comments

  1. Wzz

    Good day,
    Thanks for this. Awesome change – exactly what I needed. Except, post objects include select2 to populate select options, and after altering the post title to include the post ID, the select2 search does not pick up the search if searching for the post ID only. Any idea how to fix this?
    Thanks
    Wz

    1. David

      Actually, you can add some custom JavaScript to handle this. ACF makes available JavaScript hooks just as it does for PHP. If you take a look here, you’ll see the select2_init hook. Using that you can set the matcher property which is a function that allows you to customize the search. See the Select2 documentation for some example code for a custom search. Using that code, you could include the custom field you’ve appended to each result.

      Good luck!

  2. Laura

    Ahhhhh…almost *exactly* what I need! Thank you! My only issue is that I don’t want it adding a date to *all* post_object dropdown (yes, I have various ones in my product listings). How can I limit this to only display if there’s a specific field in the post_object? For instance, I’ve got a field called ‘event_date’ in certain post objects, and not in others. I only want to display the date in that dropdown if that field exists. Right now, it displays today’s date if the field doesn’t exist.

    Thanks in advance!

    1. David

      Laura,
      Assuming the “event_date” field is standard post meta, you can add a check for that meta:

      <?php
      function update_acf_post_object_field_choices($title, $post, $field, $post_id) {
              if ( $date = get_post_meta( $post_id, 'event_date' ) ) {
      	        $title .= ' [' . $date .  ']';
              }
      	
              return $title;	
      }
      
      add_filter( 'acf/fields/post_object/result', 'update_acf_post_object_field_choices', 10, 4 );
      ?>

      This checks to see if the “event_date” meta exists. If so, it appends that value to the title. If it doesn’t exist, it just ends up returning the original, unaltered title.

      If the “event_date” already exists in the $post parameter, you can reference that and save a query.

      Hope this helps!

  3. James

    Thanks so much for this article! I’m trying to figure out something and I’m not quite there.

    I have an “end_date” from ACF, which I am able to add a tag to the end of my dropdown. If the event is still active, it shows (ACTIVE) at the end. How would I remove an option from the dropdown if it was EXPIRED? Thanks again!

    1. David

      You could try using the `acf/fields/post_object/query` filter and add a `meta_query` to the list of query args comparing your `end_date` field.

Add Your Thoughts

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