Using the standard query_posts()
method with WordPress, it’s extremely simple to dictate in what order you want your posts and/or pages displayed when they are being shown together; as long as you only want to sort them by a single criterion. However, if you want to sort them by more than one criterion, then you have to do a little more work.
Sorting by One Field
To begin with, I will show you an example of sorting your posts or pages by a single criterion.
query_posts('orderby=post_title');
if(have_posts()) : while(have_posts()) : the_post()
// Perform your standard "the loop" actions
endwhile; endif;
You can sort your posts and/or pages by any of the following criteria: author, date (posted date), post_title, modified (modified date), menu_order, parent, ID, rand (random), meta_value (a meta_key=keyname must also be declared in the query), none (no order) and comment_count.
Sorting by Multiple Fields
I, however, had a single page I wanted to show up first in the list, then I wanted all of the other pages to show up in alphabetical order. To accomplish this, first I assigned a menu_order of 0 to the page I want listed first and 1 to all of the other pages.
To make this happen, I tried a few different variations of the standard query_posts()
method, but couldn’t get it to work for me. I tried feeding an array as the value of the orderby
clause, and then I tried feeding it a simple comma-separated list. The array generated an error message telling me that the function wouldn’t accept an array for that parameter. The comma-separated list seemed to ignore the second parameter altogether.
I then started looking for ways to run custom queries with WordPress. I came across an article in the WordPress codex explaining how to use custom SELECT queries. I then started to work on my own custom query.
To be safe, I stored the current current post ID variable and the $post and $wp_query objects in new temporary variables, as I needed to be able to access them again after I was done using my custom query. That looked something like:
global $post;
$current_page_id = $post->ID;
$original_post = $post;
$tmpquery = $wp_query;
Then, I started building my query. That ended up looking like:
$querystr = "
SELECT wposts.*
FROM $wpdb->posts wposts, $wpdb->postmeta wpostmeta
WHERE wposts.post_parent = $current_page_id
AND wposts.ID = wpostmeta.post_id
AND wposts.post_status = 'publish'
AND wposts.post_type = 'page'
ORDER BY wposts.menu_order, wposts.post_title ASC
";
When I ran this query and started my custom loop (explained in the article I linked above), I noticed that I was getting two copies of each post. I first solved this issue by creating an empty array (in my case, I called it $used
) and adding each post to that array when I looped through. If I found that the current post already existed in the $used
array, I skipped it by using code similar to:
if(in_array($post,$used)) {
continue;
}
array_push($used,$post);
Since I was not actually using any of the post meta data, I didn’t think I really needed to query the second table or perform the JOIN
(“wposts.ID = wpostmeta.post_id
“), but I went ahead and left that in there just in case I need it at a later date.
I then decided to test the query with that information removed. Lo and behold, I figured out that, without querying both tables and performing the JOIN
, I no longer ended up with doubles of each post, so I was able to remove the $used
array. My code now looks like:
$querystr = "
SELECT wposts.*
FROM $wpdb->posts wposts
WHERE wposts.post_parent = $current_page_id
AND wposts.post_status = 'publish'
AND wposts.post_type = 'page'
ORDER BY wposts.menu_order, wposts.post_title ASC
";
I also removed the $used array from my code since I no longer needed it.
So, although I couldn’t use the standard query_posts()
method, I was able to figure out how to successfully sort my pages by menu_order then post_title by simply using the get_results()
method of the WordPress database object.