We all know what the WordPress Loop is right? If not, there are many great tutorials around the web that explain the WordPress Loop.
One of the easiest ways to navigate and manipulate the loop is to use the function called query_posts. Nathan Rice calls it a WordPress developers best friend.
When you use query_posts, however, you risk the following:
- Potential to interfere with plugins which make use of the Loop.
- Potential to invalidate WordPress conditional tags.
- Having to deal with resetting, rewinding, offsetting…
I say skip query_posts. In a way you’ll still be using it, but the better (and sometimes easier) technique is to instantiate your own WP_Query object and create your own loop.
Creating Your Own Loop With WP_Query
The first step is to instantiate your own variable using the WP_Query class.
What we’ll be doing in this example is creating a common feature on blogs, which is to display a list of the recent articles.
<?php $recentPosts = new WP_Query(); $recentPosts->query('showposts=5'); ?>
All I’ve done in the above code is defined a variable named recentPosts and instantiated an instance of WP_Query.
I then used a method of WP_Query to start a query (pretty much the same thing as using query_posts). You even use the same usage parameters as query_posts.
Now it’s time to start our own loop:
<?php while ($recentPosts->have_posts()) : $recentPosts->the_post(); ?> <!-- do some stuff here --> <?php endwhile; ?>
Notice the use of the recentPosts variable to start the loop. We utilize two methods of WP_Query, which is have_posts and the_post. You can read more about those two methods on my article Global Variables and the WordPress Loop.
The beauty of this is that once you are inside your own loop, you can use the standard post tags.
The Full Code
Here’s the full code for showing the last five recent posts using your own loop:
<h3>Recent Articles</h3> <ul> <?php $recentPosts = new WP_Query(); $recentPosts->query('showposts=5'); ?> <?php while ($recentPosts->have_posts()) : $recentPosts->the_post(); ?> <li><a href="<?php the_permalink() ?>" rel="bookmark"><?php the_title(); ?></a></li> <?php endwhile; ?> </ul>
Update: Using Pagination
This comment is from Aaron Harun –
@Ron and Monika
If you use the query:
$recentPosts->query('showposts=5'.'&paged='.$paged);
it will automatically page the wury based on the page number passed
through the url eg “/page/4”
However, this doesn’t work with the “post_nav_link” function because it
only checks the $wp_query variable. To get around this you have to
trick the function by switching $wp_query on it. Add the first block
before your custom loop and the second after to achieve this effect.
<?php //query_posts('paged='.$paged); $temp = $wp_query; $wp_query= null; $wp_query = new WP_Query(); $wp_query->query('showposts=5'.'&paged='.$paged); ?>
<?php $wp_query = null; $wp_query = $temp;?>
Thanks Aaron for the contribution.
Conclusion
Defining your own loop using WP_Query is an easy way to run your own custom queries without interfering with the default Loop. It’s also a great way to run multiple loops that are completely independent of each other.
WordPress Resources mentioned:
Hi Ronald
I have a great wish:
This way is killing the next and previous link. Please show this loop with full functionable pagination or “thousands” 😉 of support threads will be open….pagination doesn’t work for me
thanks a lot
Monika
Monika,
I’m afraid I don’t know the answer to that. It looks like from the pagination code that it ties into the default loop.
It appears that you’ve found a weakness of this technique over query_posts. To be honest, I don’t think you’d really want to use pagination with this type of technique, which should be independent of the standard WordPress loop.
Perhaps someone else can chime in?
Hi Ronald
To use this loop in index.php doesn’t make sense, so I try it in archive.php , WP has the order to show 10 articles per page,
with this loop it shows 5 recent posts and 5 from the archive, because to combine two loops with if have posts …while … WP dig one’s heel in and says: 10 articles are 10 articles 😉
I have this day no time to play with your loop, but if someone would like to us it he must be aware of this 😉
kindly regards
Monika
I’ve used this method for the index page to separate a featured post:
$my_query = new WP_Query('cat=-1&showposts=1');
while ($my_query->have_posts()) : $my_query->the_post();
$do_not_duplicate = $post->ID;
... do stuff here ...
endwhile;
and further down show the rest of the posts
if (have_posts()) : while (have_posts()) : the_post();
if( $post->ID == $do_not_duplicate ) continue; update_post_caches($posts);
.. do stuff here ...
endwhile;
...pagination...
else;
endif;
The only way that I could get pagination to work was to remove one category from showing…so I chose the default uncategorized category. Since I wanted every post being under a category that I defined, it really wasn’t an issue.
I forgot to mention that with this I was also using WP-Sticky to “sticky” the featured post (sticky for single day, announcement for multiple days). Without this plugin it would just show the latest post in the featured post area.
@Monika: Thanks for that technique. I was wondering a more effective way to separate a featured post from the rest of the loop.
oh there was a fatal error if I tried to send my comments before , so I’ll try it again
@ Leland there is no loop from me in this comments
I know 5 ways to highlight the first post
http://www.texto.de/texto/5-wa.....ess-theme/
and here is my loop for the last 5 posts with pagination
OH! it is my code I’ll try it in another way
Recent Articles
rewind_posts();
$wp_query->query_vars["showposts"] = 5;
$wp_query->get_posts();
if (have_posts()) : while (have_posts()) : the_post(); ?>
...your stuff
endwhile;
…next_posts_link(‘« Older Entries’) …
.. previous_posts_link(‘Newer Entries »’) ….
endif;
regards Monika
Ronald,
You’re absolutely right. query_posts kills your other loops (if using multiple loops). I’ve been using the alternate technique for about 6 months now, and it works great!
And as far as I know, pagination only works with the default loop. It’s best to use conditional tags to qualify the standard loop if you want to keep pagination. For instance, if you want to exclude a category from the standard loop, then do this:
if have posts : while have posts : the post
if(!in_category(‘2’)) :
standard stuff like title and content
endif
endwhile
endif
That excludes any post that is in category 2 from being displayed. Pretty easy.
Thank you for the guide!
Thanks everyone for their input. I’ve amended the post with some further input.
Thanks, Ronald. This was really helpful. Is there any chance you could go into more detail about how the pagination workaround works?
Great and informative post. I’ve been learning and modifying the loop myself by following other tutorials, this is a great addition. Like Julian above, I would like to learn more about the pagination workaround though. It seems like a really great feature, especially if a page has many different loops running. Paging results seems like a really great user experience.
@Julian, WP Modder,
That would probably require a separate post for the explanation. I’ll see what I can do.
Thank you! Good guide and a perfect way to run multiple independent loops.
I use this on my site for the listing of posts on the main page, with two wp_query loops on the right side of the page. Then in my sidebar (left side) I use it for the quick thoughts (or asides as everyone calls them), the latest gallery and latest panoramic image.
So all in all when you view the main page of my Web site, that is five wp_query post loops.
How to fetch posts based on custom fields. I want to show posts that contain similar custom field value, using WP loop (so that pagination work).
This has been wonderfully helpful and clear! One q. How do I set up a query with alphabetizing and pagination?
Many thanks!
You save my life! thanks 😉
You are a godsend, thanks for your clear explanation.
How can I add a “New” image beside the latest 5 posts?
This is great, and I’ve got it working well on my site currently.
But, I’d much rather have it show posts in the same category as the post I’m viewing or posts with a similar tag. Is there a way to put variables in to the Wp_query (like tags or category of current pst)? I looked at the codex and it seems like there is I just didn’t understand what it would look like implemented in your example above.
Hi Ronald,
THANK you for this excellent (simple but effective) how-to. I am working on a theme front page using home.php where I use your technique to create serveral sections with different loops.
One section listing all sticky posts:
query(array('post__in'=>get_option('sticky_posts')));
while ( $stickyPosts->have_posts() ) :
$stickyPosts->the_post(); ?>
<?php
endwhile;
endif;
[ NOTE: I use
if (get_option('sticky_posts'))
instead ofif ( $stickyPosts->have_posts() )
here because if there are NO sticky posts, this loop would just bluntly burp out all posts! Any ideas on why that happens? ]Another listing just one category called News (if there is any):
term_id) :
$newsPosts = new WP_Query();
$newsPosts->query("cat=$news_cat&showposts=3&caller_get_posts=1");
if ( $newsPosts->have_posts() ) :
while ( $newsPosts->have_posts() ) :
$newsPosts->the_post(); ?>
<?php
endwhile;
endif;
endif;
I found that just doing multiple query_posts() will make WP ‘forget’ stuff e.g. it is doing a frontpage and suddenly conditional tags like is_front_page() or is_home() don’t work anymore. So your method came as a BIG lifesaver!
One question: Using several query_posts() gets me strange WP behaviour but I bet I could have chosen another route. What if I just took the unmodified main loop query and did several loops with conditional tags (like if( in_category(‘2’) ) for instance) to weed through all posts and exract only the ones I need for that particular section. And after each section do a rewind_posts() to set the loop back to start again… But I suspect this will be much more resource intensive when the blog is filled with hundreds of posts, or am I mistaken?
Wow, it seems a lot was lost from between the
tags in my previous post... Ronald, could you moderate it? I will try to enter the two code examples again (now a bit simplified) in the hope it will get through this time :)
...
One section listing all sticky posts:
if (get_option('sticky_posts')) :
$stickyPosts = new WP_Query();
$stickyPosts->query(array('post__in'=>get_option('sticky_posts')));
while ( $stickyPosts->have_posts() ) : $stickyPosts->the_post(); ?>
...sticky loop stuff here...
endwhile;
endif;
...
Another listing just one category called News (if there is any):
if ($news_cat = get_category_by_slug('news')->term_id) :
$newsPosts = new WP_Query();
$newsPosts->query("cat=$news_cat&showposts=3&caller_get_posts=1");
if ( $newsPosts->have_posts() ) : while ( $newsPosts->have_posts() ) : $newsPosts->the_post(); ?>
... news loop stuff here ...
endwhile;
endif;
endif;
Thanks!
Hi,
Thanks for the tutorial, very straight forward. So I tried this out on a page template of mine. The first loop is right from the original theme template and displays whatever the user has typed into a published page.
The second loop using your technique and calls a number of posts which are defined by 3 custom fields the user can set before publishing the page.
query(array(
‘showposts’ => 500,
‘category_name’ => $record_category = get_post_meta($post->ID, ‘record_category’, TRUE),
‘meta_key’ => $record_metakey = get_post_meta($post->ID, ‘record_metakey’, TRUE),
‘meta_value’ => $record_metavalue = get_post_meta($post->ID, ‘record_metavalue’, TRUE),
));
?>
So far so good, the **DO STUFF** that follows work brilliantly and I get all the records I’ve asked for. Problem is WP gets mixed up as to where it is. Instead of decided it’s looking at a specific page, it thinks it’s looking at the last entry from the second WP_Query loop.
Any ideas how I can fix this? Thanks again,
Cheers – Luke
I tried using the method described by Aaron Harun as well but that didn’t seem to work. This is what I tried using his template.
// First Loop
// Second Loop (below)
query(array(
‘showposts’ => 30,
‘category_name’ => $record_category = get_post_meta($post->ID, ‘record_category’, TRUE),
‘meta_key’ => $record_metakey = get_post_meta($post->ID, ‘record_metakey’, TRUE),
‘meta_value’ => $record_metavalue = get_post_meta($post->ID, ‘record_metavalue’, TRUE),
‘paged’ => $paged,
));?>
**** Do stuff ****
*** Navigation Code ****
I found a simple solution for the pagination problem and the comments problem.
just add this
global $wp_query;
$wp_query=$the_query;
next to you query, where $the_query = new WP_Query(….
Thats all
hi diego,
can you help here? i did what you mentioned but can get the next prev article links to work
thanks
Thanks for the code buddy. this ended a 4 hour search to this problem. I tried to add the code to show the previous post and next post and it errored out on the endif. Can you recommend a fix for that? I only want to show about three posts and have a link for the rest.
Thanks for a really useful article. I’ve just put together a function for my custom themes that improves on WordPress’ built-in pagination controls. It accepts any WP_Query object as a parameter, so it can be used with this technique (without the documented pagination issue), or with normal WP loops…
There’s some linked text in the above comment! Doesn’t seem to be to clear to me, thought I’d point it out…
Will the the following code as found in “Update: Using Pagination” work in php5?
query(‘showposts=5′.’&paged=’.$paged);
?>
As $wp_query is an object, and in PHP4, objects are passed by value while in php5 they are passed by reference will that cause a problem since $temp points to the same object in memory as $wp_query?
Oh oh! My code disappeared.
Great post!!!
Would you know how to grab the two most recent posts (with excerpt), then show the next three post titles (Just the Titles)?
Thank you!
very helpful loops from wp query. thanks for the post..
Thanks for this! I’ve been working for 6 hours straight playing with query_posts and wasn’t getting anywhere. My problem was that I wanted to show posts on a ‘page’ and had already used two loops. When you want to show posts on a page, you have to save the initial query before starting a second loop to show your posts, then when youre finished, reloading the original query…
The problem with doing this was that I wanted to add category posts to my footer so any additional query posts were only calling ‘pages’ or nothing at all.
Your tutorial helped me start a new loop for the footer and now I’m flying! Thanks, man!
Hello Great article .
I hope you can help me with something i did all that but the problem is in main page showing recent posts and in page/2 page/3 etc showing same content i want to show old posts as well can you please tell me how to do that thanks in advance .
Fahad
Thank you for the code, it is the easiest one I’ve seen so far…
Hi Ronald,
Thanks for the exellent trick with WP_Query. I hope you can help me with basic problem on wordpress loop.
I intend to make a custome query which will showcast only featured posts in my homepage. However, as on using custom query, pagination doent seem to
work.
The custom query is –
have_posts()) : $recent->the_post();?>
*** Do some stuff ***
Now, the problem is even after clicking “Older Entries” or “Newer Entries”, the page URL changes to domain.com/page/2 but the contents remain same.
It looks like pagination isnt working with WP_Query.
I would be really greateful if you can suggest something to make it work.
I’m liking this method. Any way to include an image that may already be placed within the article? Maybe get a little ol’ thumbnail or something. It seems many people are doing this as well. Anyone know how to do this?
Can someone help with this http://weblogtoolscollection.c.....nt-1319071
Hi there,
How would I display the following within this query – & in this order;
the post date
the post title (which is a link to the post)
the post excerpt
and a read more link
thanks in advance!
Jas
Many thanks for help, it really helped! 🙂
Why? Oh why didn’t I find this in the morning? My comments pagination was broken on index.php because of my multiple loops. I was resetting the wp_query but after the comments. It took me 8 hours to fix this and I still have some more problems – the post pagination is not working and the comments Next button takes me to single.php
Sweeeet! and easy. I was trying to accomplish this with query_posts and it was messing up the loop by pulling the news section into the featured posts section. This is easier and it works.
Thanks for the post, very usuful.
I’ve got a question. Is it possible to loop through the results of WP_Query without the line $recentPosts->the_post(); because that one overwrites the global $post, which I want to preserve as I need to use the original $post after the custom loop. Hope that make sense.
Would really appreciate any help!
Thanks.
Yes its possible but it depends how you want to bend the loop according to you… Dasha May i know what type of change are you trying.. 🙂
Awesome!!!! One more addition to my favorite WP blogs…. Thanks 🙂
I have a question. I have the custom loop working but I need it to sort by certain categories in alphabetical order. Any suggestions on how I can accomplish this?
I am a beginner at PHP so any help would be great!
You mean you want posts of a certain category to appear in alphabetical order?
Either create a custom template file named category-XX.php (where XX is the specific category ID number) and change the query parameters as described on http://codex.wordpress.org/Alphabetizing_Posts
…or…
Use a custom function in your themes functions.php and hook it with a filter as described on http://codex.wordpress.org/Cus.....ount_Limit
I’m trying to use this code with pages and it still shows me posts. I have read the codex but cannot make this work… Anyone?
Oh, God!
” … because it only checks the $ wp_query variable …”
Thanks It’s very helpfully!
how do i exclude two categories using the wp_query loop?