September 29, 2021

Ordering WordPress posts by multiple custom fields

Recently I had to order a custom post type archive page by two different custom fields (set up via ACF). In this instance the point was to order by last name and then first name on a staff listing page. Took a little digging to figure out how to do this exactly, helped by John Huebner on the ACF forums.

I generally use the pre_get_posts action to alter these queries. I ended up with this code

function pilotmade_leadership_archive( $query ) {
	
	if( $query->is_main_query() && is_post_type_archive( 'person' ) ) {
		
		$meta_query = array(
			'first_name' => array(
				'key' => 'first_name',
				'compare' => 'EXISTS'
			),
			'last_name' => array(
				'key' => 'last_name',
				'compare' => 'EXISTS'
			),
		);
		$order_by = array(
			'last_name' => 'ASC',
			'first_name' => 'ASC'
		);
		
		$query->set( 'meta_query', $meta_query );
		$query->set( 'orderby', $order_by );
		$query->set( 'posts_per_page', -1 );
	}
}
add_action( 'pre_get_posts', 'pilotmade_leadership_archive' );

So the key is to create a meta_query array that has named values. In this instance all I wanted to know is if the first/last names existed, but you could do other tests.

In the end, simple, but it took about 15 minutes to find the syntax, so hopefully this helps someone.