5

I am using the query_posts function to list a 10 specific posts which lookup by post id.

I have an array which looks like this..

Array
(
    [0] => 17983
    [1] => 17932
    [2] => 18030
    [3] => 18016
    [4] => 17972
    [5] => 18013
    [6] => 18035
    [7] => 17959
    [8] => 18020
    [9] => 18039
)

I would like to query posts showing it in that specific order, however with my code it shows them in a random order of its own.

Here is the argument I use for query posts:

$args = array(
    'post_type' => 'post',
    'post__in' => $post_ids,
    'numberposts'     => 10,
);

$post_ids is the array which I have posted above.

How can I alter my code to query the posts and show them in the order of the array?

5 Answers 5

5

If the query is only for a small number of posts, then as linked to by Alex you can sort in php. However, this does not scale well.

As suggested by Kovshenin - a better alternative is to use posts_orderby filter:

$post_ids = array(83,24,106,2283,14);
$args = array(
    'post_type' => 'post',
    'post__in' => $post_ids,
    'numberposts'     => 10,
);

//Callback to filter the ORDER BY part of the query
function wpse67823_orderby_post_in($orderby, $query){
     global $wpdb;

     //Remove it so it doesn't effect future queries
     remove_filter(current_filter(), __FUNCTION__);

     $post__in = implode(',',$query->get('post__in'));

     return "FIELD( {$wpdb->posts}.ID, $post__in )";
 }

//Add filter and perform query
add_filter('posts_orderby','wpse67823_orderby_post_in',10,2);
$wpse67823_query = new WP_Query($args);

3.5+

WordPress 3.5 will see an additional value accepted by WP_Query for orderby: 'post__in'. See this trac ticket: http://core.trac.wordpress.org/ticket/13729

3
  • Thanks for the code, although I have tried it and also made edits to it, I am unable to get it to query the posts in the order of the array (Sorry to be a pain)
    – Imran
    Oct 11, 2012 at 0:25
  • I've edited my answer, the above works for me. Oct 11, 2012 at 1:24
  • Just tested again now, it does work :D I think it was an issue with the while statment I had. Thanks for the help Stephen!
    – Imran
    Oct 12, 2012 at 0:08
3

Based on @Stephen Harris answer, for Wordpress 3.5+ the easiest option seems to be ordering by post__in.

Here is the example:

$post_ids = Array(12, 15, 18, 8, 10, 5);

$args = array(
  'post_type' => 'post',
  'post__in' => $post_ids,
  'numberposts' => 10,
  'orderby' => 'post__in'
);
$posts = WP_Query($args); // or any other method that uses WP_Query args e.g. get_posts()

// as a result you will get posts in order: 12, 15, 18, 8, 10, 5

I've tested that myself on a Wordpress 4.7 site and it works as expected.

2
  • 1
    This should be the accepted answer. It doesn't reply on filters, it just uses the built in orderby feature. Oct 4, 2019 at 19:48
  • Best and simple answer, should be accepted answer!
    – Stefan
    Mar 13, 2020 at 10:39
1

You will need to hijack the resulting SQL query during posts_orderby and use MySQL's ORDER BY FIELD() function with a comma-separated list from your array. Here's more info about the FIELD function: http://www.electrictoolbox.com/mysql-order-specific-field-values/

I did this quite some time ago when I had Sphinx return a list of post IDs ordered by relevance, so I had to select them with WP_Query in that very same order. FIELD() during the posts_orderby filter worked like a charm.

Also, if you're using query_posts to alter the main query, it's not the best way to do it. @Alex mentioned WP_Query, which is not really different from query_posts and is also a bad way to (make it seem like you) alter the main query.

The correct way would be to use the pre_get_posts action, and change the passed in by reference $query object. You can learn more about pre_get_posts here: http://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts

Hope that's helpful. Cheers!

5
  • Oh, and you can use the php implode function to convert your array into a comma-separated list of IDs which you can use in that FIELD query :)
    – kovshenin
    Oct 10, 2012 at 21:53
  • 1
    The query isn't the main query, its used for a charting system on the sidebar. I've had a look at codex.wordpress.org/Plugin_API/Filter_Reference/posts_orderby. By adding this function though its going to alter the main query rather than the sidebar query isnt it?
    – Imran
    Oct 10, 2012 at 22:05
  • @Imran you can target the specific query by adding the filter immediately before the WP_Query and removing it again afterwards. Oct 10, 2012 at 23:32
  • @StephenHarris: Can you show me an example of this?
    – Imran
    Oct 10, 2012 at 23:46
  • @Imran, if you indeed need a secondary loop, then new WP_Query or get_posts will work best. posts_orderby gets called on every query. As Stephen suggested, you can add the filter before running your query and remove it soon after.
    – kovshenin
    Oct 11, 2012 at 7:28
0

Here is a simpler Workaround to achieve this, simply create a custom field for each one of these posts with the same name ans set your desired order, ex:

  • for post with id = 17983 set a custom field named my_custom_order = 1
  • for post with id = 18030 set a custom field named my_custom_order = 2
  • for post with id = 18016 set a custom field named my_custom_order = 3
  • you get the point

then in your query simply order by that custom field:

$args = array(
    'post_type' => 'post',
    'post__in' => $post_ids,
    'posts_per_page' => 10,
    'meta_key' => 'my_custom_order',
    'orderby' => 'meta_value',
    'order' => 'ASC'
);

Note: Once you do that (set the custom field for these posts) you can remove the 'post__in' => $post_ids, parameter since only posts with the custom field of my_custom_order will be queried from the database.

-1

First of all, don't use query_posts(), use WP_Query().

Second, change your array to just the post ids.

from:

[0] => 17983
[1] => 17932

to

array( 17983, 17932 )

EDIT: Look HERE for a reference.

1
  • 2
    Huh? How exactly is [0] => 17983, ... different from array( 17983, ... ) :) The former is just a print_r of the latter.
    – kovshenin
    Oct 10, 2012 at 21:53

Your Answer

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

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