I have a People post type with a Person Type taxonomy (e.g. “Staff”). On the Person Type Term Archive pages, I want to sort by a “Sort Name” custom field. To do so, I’m using a pre_get_posts
call:
<?php
function my_query_tweaks( $query ) {
// stop immediately if we're in the admin or not working with the main query
if( is_admin() || !$query->is_main_query() )
return;
// order people by sortname
if( is_post_type_archive( 'ciswa_people' ) || is_tax( 'ciswa_person_type' ) ) {
$query->set( 'meta_key', 'cis_sort_name' );
$query->set( 'orderby', 'meta_value' );
$query->set( 'order', 'ASC' );
}
}
add_action( 'pre_get_posts', 'my_query_tweaks' );
However, when I do this, the term archive pages return no results! Commenting out the meta_key
line brings up the correct posts but, of course, unordered.
When I look at the query WordPress is generating, I think the issue is that WordPress is trying to also query posts based on the meta_key rather than just ordering by it. From $wp_query
on the relevant empty taxonomy term archive page:
["tax_query"]=>
object(WP_Tax_Query)#343 (2) {
["queries"]=>
array(1) {
[0]=>
array(5) {
["taxonomy"]=>
string(17) "ciswa_person_type"
["terms"]=>
array(1) {
[0]=>
string(5) "staff"
}
["include_children"]=>
bool(true)
["field"]=>
string(4) "slug"
["operator"]=>
string(2) "IN"
}
}
["relation"]=>
string(3) "AND"
}
["meta_query"]=>
object(WP_Meta_Query)#344 (2) {
["queries"]=>
array(1) {
[0]=>
array(1) {
["key"]=>
string(13) "cis_sort_name"
}
}
["relation"]=>
string(3) "AND"
}
…and…
["request"]=>
string(498) "SELECT SQL_CALC_FOUND_ROWS fi_posts.ID FROM fi_posts INNER JOIN fi_term_relationships ON (fi_posts.ID = fi_term_relationships.object_id) INNER JOIN fi_postmeta ON (fi_posts.ID = fi_postmeta.post_id) WHERE 1=1 AND ( fi_term_relationships.term_taxonomy_id IN (6,10) ) AND fi_posts.post_type = 'ciswa_people' AND (fi_posts.post_status = 'publish' OR fi_posts.post_status = 'private') AND (fi_postmeta.meta_key = 'cis_sort_name' ) GROUP BY fi_posts.ID ORDER BY fi_postmeta.meta_value ASC LIMIT 0, 10"
'meta_key' => 'keyname'
must be part of the query to be able to sort by its value.Unfortunately, that will immediately result in the query being limited to posts where the key is set (its value can be empty, but it must exist).
Hence, either consider the method s_ha_dum linked to in the question comments, or choose to do the sorting after the query.
Let me offer an approach to that (untested, just a concept):
Note: The above format of the conditional in the
usort
callback serves the purpose of readability. In production, it can be a one-liner:Head desk
I had the
meta_key
wrong. @Johannes Pille’s answer was the key in that it pointed me to the fact that if the key was there this shouldn’t be a problem. It was there but I wasn’t using it.