Auto-generate your post title with ACF data

Auto-create your post title with ACF data

Every once in a while you may find yourself with a custom post type that doesn’t really need a title. Take events for example. They will have dates, places and venues, but in many cases giving an event a name is redundant. And anything that is redundant is extra work.

Or maybe you have a case where you do want to use the title—be it for a page, a post or a custom post type— but it could make your job a lot easier to simply define it automatically, using custom fields from your post.

I’m sure there’s a way to do this with WordPress’ native custom fields, but in my case I’m using Advanced Custom Fields. ACF provides a hook, acf/update_value, for modifying the value of a field before it’s saved to the database. This can be used in tandem with wp_update_post(); to simultaneously inject data into your post title, slug, content, etc.

Cool, huh?

As an easy example, let’s imagine a scenario for our Events custom post type where we’ll use the date of the event and the city where the event will take place to create a title and slug for our post.

[pastacode lang=”php” message=”” highlight=”” provider=”manual”]

// Auto-populate post title with ACF.
function jb_update_postdata( $value, $post_id, $field ) {
	
	$date = strtotime(get_field('date', $post_id));
	$city = get_field('cities', $post_id). ' ' . $value;
	
    $formatted_date = date_i18n('d M Y', $date);
    $title = $formatted_date .' - '. $city;

	$slug = sanitize_title( $title );
  
	$postdata = array(
	     'ID'          => $post_id,
         'post_title'  => $title,
	     'post_type'   => 'events',
	     'post_name'   => $slug
  	);
  
	wp_update_post( $postdata );
	
	return $value;
	
}
add_filter('acf/update_value/name=date', 'jb_update_postdata', 10, 3);
add_filter('acf/update_value/name=cities', 'jb_update_postdata', 10, 3);

[/pastacode]

If you’re working in English, then formatting the date is an extra step you don’t need. Also, it’s likely that specifying the post type in the $post_data array is unnecessary, unless you share custom fields across multiple post types and only want to auto-populate one type and not another.

In my current working case, I wanted to go a little further and give a range of dates to my post titles. Why? The titles are not used on the front-end of the site, because events are only displayed as a listing and never as single posts. But in the admin they need to be easy to identify in order to go back and change them. They need to be nice to look at.

For this project, each event has a start date and an end date. Sometimes, they are the same date. So I created a conditional scenario that compares the dates so that the display in the admin columns is easy on the eyes no matter what the range of dates are.

[pastacode lang=”php” message=”” highlight=”” provider=”manual”]

// Auto-populate post title with Event dates.
function jb_update_postdata( $value, $post_id, $field ) {
	
	$date_start = strtotime(get_field('date_start', $post_id));
	$date_end = strtotime(get_field('date_end', $post_id));
	$city = get_field('cities', $post_id);
	
	if( $date_start == $date_end ) {
		
	     $start = date_i18n('d M Y', $date_start);
		
	     $title = $start;
		
	} else {
		
	     $start = date_i18n('d M', $date_start);
	     $end = date_i18n('d M Y', $date_end);
	
	     $title = $start .' - '. $end;
	}

	$slug = sanitize_title( $title );
  
	$postdata = array(
	     'ID'	   => $post_id,
    	 'post_title'  => $title,
	     'post_type'   => 'events',
	     'post_name'   => $slug
  	);
  
	wp_update_post( $postdata );
	
	return $value;
	
}
add_filter('acf/update_value/name=date_start', 'jb_update_postdata', 10, 3);
add_filter('acf/update_value/name=date_end', 'jb_update_postdata', 10, 3);
add_filter('acf/update_value/name=cities', 'jb_update_postdata', 10, 3);

[/pastacode]

You’ll notice that even though I’m not using $city in the post title, I’ve still included it in the act/update_value. Why? To be honest I have no idea. It is quite possibly a bug with ACF, but after spending hours turning it every which-a-way, I concluded that if you want to work with two dates, then you need to include a separate field—it doesn’t matter which one or what type it is—or the secondary date with display as the current date. If someone has a better explanation or solution for this, I’m a taker smile

To finish up, it makes sense to rename the Title column in my admin to correspond to the Event dates.

[pastacode lang=”php” message=”” highlight=”” provider=”manual”]

//Sets column headers
function set_custom_event_columns($columns) {
    unset( $columns['author'] );
    unset( $columns['date'] );
    unset( $columns['title'] );
    $columns['title'] = __( 'Dates', 'jb' );
    $columns['cities'] = __( 'City', 'jb' );
    $columns['venues'] = __( 'Venue', 'jb' );

    return $columns;
}
add_filter( 'jb_edit-events_columns', 'set_custom_event_columns' );

[/pastacode]

The result:
Screenshot custom columns

The post title is completely hidden when I create a new event. It is then generated automatically when I publish or update the event, using data from my custom fields – in this case, the event dates.

Fancy!

**UPDATE March 5, 2015 **

Thanks to feedback on the interwebs, I’ve updated the above code, removing an unnecessary (and undefined) global variable.

I’ve also run into an important issue regarding the taxonomy field. In my current project, the cities come from a pre-defined list in a custom taxonomy. As is, the above code will only post the ID of the city, and not it’s name. And, more importantly, it will throw an error if you try to modify the post type. Essentially modifying a post type using this filter will try to write over the data (this is my understanding in any case, please correct me if you think I’m wrong), which is not possible in the case of a pre-populated list of taxonomies. In other words: more testing to be done, the above will NOT work with taxonomies. thnx!

**UPDATE May 23, 2015**

Since the above update, ACF has made vast improvements to the taxonomies field – haven’t tested myself yet, but worth a shot!