1

I'm not sure if im going about this the right way or not, seems to be alot of people doing this, but with completely different ways of doing it from queries in templates to functions so im not sure which route to go down.

I have a custom post type (business) which has featured posts, Each of these posts have a "featured_listing" post_meta which is either EMPTY or "featured-listing" value** attached to the post. I'd like to display the posts which do not have an empty post_meta value above all other posts in search results and categories.

**Note the - rather than _ for the value.

This is what I thought might work, but I'm starting to think I'm barking up the wrong tree.

// Order posts by meta data
function custom_special_sort( $query ) {
    //is this the main query and is this post type of post
    if ( $query->is_main_query() && $query->is_post_type( 'business' ) ) {
        //Do a meta query
        $query->get_post_meta(get_the_ID(), "featured_listing", TRUE);

        //sort by a meta value
        $query->set( 'orderby', 'featured_listing' );
        $query->set( 'order', 'ASC' );
    }
}
add_action( 'pre_get_posts', 'custom_special_sort' );

I've also just tried to do it slightly differently, below. But could do with some guidance as to why its not working or if im even doing it correctly:

    function custom_special_sort( $query ) {
    // Check this is main query and other conditionals as needed
    if ( $query->is_main_query() && $query->is_post_type( 'business' ) ) {
        $query->set( 
          'meta_query', 
          array( 
            array(
              'key' => 'featured_listing',
              'value' => 'featured-listing',
              'orderby' => 'featured_listing',
              'order' => 'DESC'  
            )
          )
        );
    }
  }
add_action( 'pre_get_posts' , 'custom_special_sort' );
2
  • What exactly do you mean by "isn't working" - e.g. are you getting an error, are you getting the wrong results, are they not ordered as expected (and if not, how are they ordered)? Its difficult to find a problem when we don't know what exactly we're looking for :) Commented Oct 17, 2017 at 23:44
  • Sorry you are absolutely right, It's basically not re-ordering so the categories/search are still ordered in the normal wordpress date based ordering. So for example I created a "featured-listing" first, i then created a normal listing. Which means the normal listing is currently the newest and therefore is being displayed at the top of the page. What id like to do is give "featured" listings priority at the top of search results and categories all the time. With the first submitted being at the top and future submissions being below.
    – Randomer11
    Commented Oct 18, 2017 at 7:50

2 Answers 2

1

You have a couple of issues with the code you are trying.

To check the query is for your CPT archive: You are using $query->is_post_type() but it doesn't work (as far as I know, its not even a function). Instead you can use either:

if (is_post_type_archive('business')) {...}

or (if its not only on the archive page)

if ($query->get('post_type') == 'business') {...}

To order by meta value in pre_get_posts, you need to set the meta_key as well as the orderby (and optionally order).


Complete Function: Applying these to your "custom_special_sort" function, we get:

function custom_special_sort( $query ) {

    // if is this the main query and is this post type of business
    if ( $query->is_main_query() && is_post_type_archive( 'business' ) ) {

        // order results by the meta_key 'featured_listing'
        $query->set( 'meta_key', 'featured_listing' );
        $query->set( 'orderby', 'featured_listing' );
        $query->set( 'order', 'DESC' );
    }
}
add_action( 'pre_get_posts', 'custom_special_sort' );
8
  • Thanks for your time with this, I've tried the above and it still didnt work in respects of reordering anything in categories, where was no errors either. However when using search, I got this error : WordPress database error: [Not unique table/alias: 'wp_postmeta'] SELECT SQL_CALC_FOUND_ROWS DISTINCT wp_posts.ID FROM wp_posts LEFT JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) LEFT JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id WHERE 1=1 AND (
    – Randomer11
    Commented Oct 18, 2017 at 10:07
  • Thats strange. I presume its because it is trying to join to the wp_postmeta twice: INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) LEFT JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id. Are you using the standard Wordpress loop on your page that shows the posts, or a custom query using WP_Query (or other function)? Or do you have any other functions hooking into the query that could be including the postmeta table a second time?I see reference to acf-disabled in the query... what could be including posts with acf-disabled status, maybe its it? Commented Oct 18, 2017 at 10:15
  • I use the standard loop in the templates so no additional queries at that point. I did see the ACF disabled which I didnt know what it represented. The post_meta ( featured_listing ) is created with ACF ( advanced custom fields )
    – Randomer11
    Commented Oct 18, 2017 at 10:35
  • @Randomer11 The code in my answer works with ACF because I use it myself, so I'm afraid you're going to have to troubleshoot your setup to find what's causing the duplicate wp_postmeta join. First, as wp_postmeta is already being joined, try removing the $query->set( 'meta_key', 'featured_listing' ); from the function above. Then try disabling all plugins to except ACF to test in any of those cause it, if that doesn't change anything, try using one of the default WP themes with nothing added but your CPT and the function above. If that still doesn't work then you might need to look at ACF. Commented Oct 18, 2017 at 10:44
  • 1
    @Randomer11 Not right now, but I'll take a look later if you still haven't tracked down the issue! Commented Oct 18, 2017 at 10:57
0

I have marked Fluffykittens answer above as the correct answer. I wanted to extend the answer ( Hopefully it will help someone else ).

With the answer provided by Fluffykitten I found that with my particular theme, I'm using different loop for archives and custom taxonomy which resulted in the re-ordering of posts working on my search archives where is_post_type_archive was true. However my taxonomy archives the reordering wasnt happening, so changing the query to include is_tax made it work.

Not sure if its the best way of adding to the query as im a php novice, but it works. Someone is welcome to correct/improve :)

function custom_special_sort( $query ) {

    // if is this the main query and is this post type of business

    if ( ($query->is_main_query() && is_post_type_archive('business')) || (is_main_query() && is_tax ('location')) ) {

        // order results by the meta_key 'featured_listing'
       $query->set( 'meta_key', 'featured_listing' );
        $query->set( 'orderby', 'featured_listing' );
        $query->set( 'order', 'DESC' );
    }
}
add_action( 'pre_get_posts', 'custom_special_sort' );
7
  • 1
    Just be careful of the combination of your conditions in your if statement - for example, should this be if ($query->is_main_query() && is_post_type_archive('business') or is_main_query() && is_tax ('location') )? If so, you need to put the 2 separate clauses in brackets to associate them, e.g. if ( ($query->is_main_query() && is_post_type_archive('business')) || (is_main_query() && is_tax ('location')) ) Commented Oct 18, 2017 at 13:38
  • Thank you I know understand and have corrected my Operator :)
    – Randomer11
    Commented Oct 18, 2017 at 13:44
  • Did it make any difference or are you still getting a conflict? Commented Oct 18, 2017 at 13:53
  • Conflict with the other function still exists unfortunately. Will have another look at it shortly see if i can find a work around
    – Randomer11
    Commented Oct 18, 2017 at 16:59
  • Sorry, I couldn't get back to you because I'd do so some work of my own! Is you page showing as the results of a search? Thats the only reason I can think if that this wouldn't work, because the if ( is_search() ) condition in the code from adambalee.com should prevent that code from changing the query. Commented Oct 20, 2017 at 17:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.