How can i order by existence of thumbnail in WordPress?

My client asked me to order the posts by thumbnail, so I need to sort the post first with the thumbnail, then after without the thumbnail.

Here is my code:

Read More
$the_query = new WP_Query(array(
               'post_type' => 'veiculos',
               'posts_per_page'=> -1,
               'meta_key' => '_thumbnail_id',
               'orderby' => 'meta_value_num',
               'order' => 'DESC',
               'tax_query' => array(
                 array(
                   'taxonomy' => 'categoria-veiculo',
                   'field' => 'id',
                   'terms' => 5
                 )
               )
           ));

But what happens is that when i put the meta_key the post that havent thumbnail dont show.

Related posts

Leave a Reply

2 comments

  1. This is an interesting issue. WordPress currently doesn’t have a method to get all the posts with thumbnails and without thumbnails in one query with their inbuilt WP_Query method. But we can do a hack for that, probably not the best I think but will work 🙂

    Add this function in your themes functions.php file

    function remove_metakey ($where) {
    
        global $wpdb;
    
        $where = str_replace("AND (".$wpdb->postmeta.".meta_key = '_thumbnail_id' )", "", $where);
    
        return $where;
    }
    

    Add this filter just before you call new WP_Query Object

    add_filter ('posts_where_request', 'remove_metakey');
    

    So the full thing will look like:

    add_filter ('posts_where_request', 'remove_metakey');
    
    $the_query = new WP_Query(array(
                   'post_type' => 'veiculos',
                   'posts_per_page'=> -1,
                   'meta_key' => '_thumbnail_id',
                   'orderby' => 'meta_value_num',
                   'order' => 'DESC',
                   'tax_query' => array(
                     array(
                       'taxonomy' => 'categoria-veiculo',
                       'field' => 'id',
                       'terms' => 5
                     )
                   )
               ));
    

    You have to add the filter before you call the WP_QUery object else it will not work. Also don’t add this filter in your functions.php file because then it will be rendered when ever posts_where_request is made.

    What this does is that when we are executing the query with WP_Query object, it calls the posts_where_request. We are hooking our own function with posts_where_request. So when posts_where_request is called our function will be rendered. In our function we are using str_replace to replace the meta_key part in the $where value and returning it. This will remove the meta_key condition in where part in the query.

    UPDATE :

    I have found the correct method to remove the meta key from where condition using WordPress hook. This is much better and cleaner way to do :

    Add this hook before you call the WP_Query object. Instead of the earlier hook use this.

    add_filter ('get_meta_sql', 'remove_metakey');
    

    Now replace the earlier function with this :

    function remove_metakey ($array) {
    
        $array['where'] = ''; //you can also use unset, but setting the value to null is better to avoid warnings
    
        return $array;
    }
    

    The complete thing will be :

    add_filter ('get_meta_sql', 'remove_metakey');
    
    $the_query = new WP_Query(array(
                   'post_type' => 'veiculos',
                   'posts_per_page'=> -1,
                   'meta_key' => '_thumbnail_id',
                   'orderby' => 'meta_value_num',
                   'order' => 'DESC',
                   'tax_query' => array(
                     array(
                       'taxonomy' => 'categoria-veiculo',
                       'field' => 'id',
                       'terms' => 5
                     )
                   )
               ));
    

    This is the correct way to do it. It sets the where value to null thus preventing an additional meta key condition in the SQL query.

    Remember add this filter only when you need. Also don’t add this in functions.php, then it will be executed each time the get_meta_sql function is called.

    Hope this helps you 🙂

  2. why not making two queries: the first returning only posts with thumbnails, ordered as you like, and the second returning only posts without thumbnails, ordered also the way you like.

    In other words, your first query will contain the posts with thumbnails, and the second will contain all your posts with a conditionnal statement inside loop using has_post_thumbnail function.

    I think this approach will make you gain time, because the issue your are looking to resolve need more time in searching to find a solution with one query.

    Good luck