plugins – Order custom post type by posts with most likes first
Yes, there is.
First off, you need to use a meta_query
with 2 clauses, one which selects posts having the meta, and the second clause with a 'compare' => 'NOT EXISTS'
which selects posts without that meta.
So in your $args
array, just replace the 'meta_key' => 'pld_like_count',
with this, and note that the array key pld_like_count
is required:
'meta_query' => array(
// Make sure the relation is OR.
'relation' => 'OR',
// Selects posts having the meta.
'pld_like_count' => array(
'key' => 'pld_like_count',
'type' => 'NUMERIC',
),
// Selects posts without the meta.
array(
'key' => 'pld_like_count',
'compare' => 'NOT EXISTS',
),
),
Now replace the 'orderby' => 'meta_value_num title',
with 'orderby_case' => 'pld_like_count',
where orderby_case
is a custom query arg which we’ll use to group the posts.
Then add this to your functions file (functions.php
) or your plugin:
add_filter( 'posts_orderby', 'my_idea_posts_orderby', 10, 2 );
function my_idea_posts_orderby( $orderby, $query ) {
$clause_key = $query->get( 'orderby_case' );
if ( 'pld_like_count' === $clause_key ) {
$clauses = $query->meta_query->get_clauses();
if ( isset( $clauses[ $clause_key ] ) ) {
global $wpdb;
// Get the table alias used for the meta query clause.
$alias = $clauses[ $clause_key ]['alias'];
return "
# Group the posts.
(CASE
# Posts having the meta.
WHEN $alias.meta_key = 'pld_like_count' THEN 1
# Posts without the meta.
ELSE 2
END) ASC,
# Sort the posts.
(CASE
# Sort by the likes count.
WHEN $alias.meta_key = 'pld_like_count' THEN $alias.meta_value+0
# Sort by the post title.
ELSE $wpdb->posts.post_title
END) DESC";
}
}
return $orderby;
}
So yes, that’s a pretty complex sorting, but that’s how would you do it at the database level, where both posts having the meta and posts not having that meta, are included, and that they are sorted first by the likes count and then the post title for those without the meta.
See https://dev.mysql.com/doc/refman/5.7/en/flow-control-functions.html#operator_case for information on the CASE
operator used in the above ORDER BY
clause.
Leave an answer