I'm trying to improve my post sorting by using multiple criteria, but I want specific orders for different values. For example, I have a meta_key called 'featured' that I want to move any post up to the top. For matching 'featured', it should sort by title.

The problem is that I can only define one "order" key in the query_posts function.

                                        'post_type'         => 'portfolio-item',
                                        'post_status'       => 'publish',
                                        'caller_get_posts'  => 1,
                                        'paged'             => $paged,
                                        'meta_key'          => 'featured',
                                        'orderby'           => 'meta_value title',
                                        'order'             => 'desc asc',

This is the parameter array I'd like to use (notice the multiple order values. Unfortunately, this doesn't seem to be the correct form. Any suggestions?

  • You should be able to provide all of the same arguments (with the exception of maybe a variable name being different) for query_posts, new WP_Query and get_posts.
    – Jared
    Commented Jan 25, 2012 at 20:18
  • I sorted it out by getting all posts and sorting manually. I still don't think any of those query solutions provide multiple sorting directions. Commented Jan 25, 2012 at 21:25
  • Oh, well they do. But I think you haven't turned all the funky PHP and WP debug/error handling on and missing the notes.
    – kaiser
    Commented Oct 4, 2012 at 9:19

1 Answer 1



The query functions, like get_posts(), query_posts() call a new WP_Query inside - they're just wrappers.

The more important thing is what goes on in the class WP_Query. Specifically inside WP_Query -> get_posts(). When you add an orderby argument, then the following happens:

  1. WP checks if it set. If not, then it uses the $wpdb->posts.post_date and appends the `order value to it.
  2. If you set it to 'none', then there's no order applied.
  3. In every other case, the order will be used.

But... there're "allowed orderby" values:

$allowed_keys = array('name', 'author', 'date', 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand', 'comment_count');

For meta key/value pairs, there's a special case: If the meta key isn't empty, the meta_key value is added to the allowed keys, as well as meta_value and meta_value_num.

The function than explodes the orderby string to an array and loops through. Everything that matches gets added to a new array, which is then imploded (separated by a comma) after the loop and added to the SQL query string. If the resulting array was empty, then - again - the "$wpdb->posts.post_date" followed by the order will be taken. If that is empty too, then you'll see the same result as with none.

So if you're adding anything like a meta key and a meta value, then you should get the following added to your query:


Post Type(s)

Your post type arg gets added to the WHERE clause like this:

 AND $wpdb->posts.post_type = 'portfolio-item'

What I think is wrong in here:

  1. You can't add asc desc as order statement. The order must be either ASC or DESC (upper-/lowercase doesn't matter). This won't work and will likely break.
  2. I'm pretty sure, that 'portfolio-item' isn't the actual post type name. I guess it's just portfolio. Be sure to call whatever the post type is named inside

    var_dump( array_keys( (array) $GLOBALS['wp_post_types'] ) );
  3. caller_get_posts is a pre 3.1 argument. You should already get a note at the top/beginning of your code, as the following _deprecated_argument() is called before any query string is even built:

    "caller_get_posts" is deprecated. Use "ignore_sticky_posts" instead.

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.