Paging and Custom WordPress Loops
If you like this post, please subscribe to our RSS feed to read our new posts every day.
Last week I published two articles using custom loops. The first was about how to create a custom loop. The second was how to retrieve posts based on custom fields. In both articles, several readers commented that they would like to see paging and have it explained.
I’d like to thank Aaron Harun from Anthology of Ideas for supplying the code used in this post.
Paging, and why it doesn’t work with WP_Query
The paging magic happens in a file called ‘link-template.php‘ in the ‘wp-includes‘ folder.
Most themes have basic paging built in, with the help of two functions: next_posts_link and previous_posts_link.
These functions, as well as several others, make use of a global variable called $wp_query. This variable is actually an instance of the WP_Query object. However, when we create our own instantiation of WP_Query, we don’t have this global variable $wp_query, which is why paging will not work.
How to make paging work with a custom loop
As Aaron mentioned, the paging functions rely on a global variable called $wp_query. The “fix” is to trick WordPress into using the global $wp_query variable when using our own custom loops.
In the example below, I’ll show how to display the last five recent articles with our own custom loop with paging intact.
<h3>Recent Articles</h3> <ul> <?php $temp = $wp_query; $wp_query= null; $wp_query = new WP_Query(); $wp_query->query('showposts=5'.'&paged='.$paged); ?>
The first thing the code does (shown above) is create a temporary variable to hold a reference to global variable $wp_query. The wp_query variable is set to null, and we instantiate a new WP_Query object.
Notice in the query above that we have these parameters:
$wp_query->query('showposts=5'.'&paged='.$paged);
The paged portion of the query is critical in order to have paging.
From there, we can now do our own query and begin our custom loop.
<?php while ($wp_query->have_posts()) : $wp_query->the_post(); ?> <li><a href="<?php the_permalink() ?>" rel="bookmark"><?php the_title(); ?></a></li> <?php endwhile; ?> </ul>
Notice in the above code that the loop is initiated using the $wp_query variable. Since we are using $wp_query, paging should work.
Now it’s time to create our navigation links for paging:
<div class="navigation"> <div class="alignleft"><?php previous_posts_link('« Previous') ?></div> <div class="alignright"><?php next_posts_link('More »') ?></div> </div>
And finally, we assign the variable $wp_query back its original value using the $temp variable we set earlier.
<?php $wp_query = null; $wp_query = $temp;?>
The Full Code
<h3>Recent Articles</h3> <ul> <?php $temp = $wp_query; $wp_query= null; $wp_query = new WP_Query(); $wp_query->query('showposts=5'.'&paged='.$paged); ?> <?php while ($wp_query->have_posts()) : $wp_query->the_post(); ?> <li><a href="<?php the_permalink() ?>" rel="bookmark"><?php the_title(); ?></a></li> <?php endwhile; ?> </ul> <div class="navigation"> <div class="alignleft"><?php previous_posts_link('« Previous') ?></div> <div class="alignright"><?php next_posts_link('More »') ?></div> </div> <?php $wp_query = null; $wp_query = $temp;?>
Additional Applications
The above technique can allow paging for custom loops. All you have to do to modify this is to use your own query parameters, and change the code within the custom loop.

Recent Articles Example
The above example is live at raproject.com under Recent Articles.
Conclusion
Paging is a powerful WordPress feature, and fortunately you can use it when defining your own custom loops.
The example I demonstrated was rather generic, but hopefully you’ll be able to apply it to your own custom loops where paging is necessary.
Please feel free to share your own examples or problem code in the comments. If you use code, please use something like pastebin since some code isn’t allowed in the comment section.
Visitors who read this post, also read:
Related posts from the past
- How to: Offsets and Paging
- Define Your Own WordPress Loop Using WP_Query
- How To: Avoid Duplicate Posts
- How to Only Retrieve Posts With Custom Fields
- Global Variables and the WordPress Loop
- Error Management for WordPress Plugins
- Plugin Deactivation Issues Solved With Actions and Filters
- Managing Trackbacks and Pingbacks in Your WordPress Theme
- The "More" Tag on a WordPress Page
- Removing Width/Height from the Image Uploader













Comments RSS
My blog has nothing with pages in the loop but its a good example of the category/gallery function that has become available via 2.5. An example of this can also be seen on Matt’s page…
[Reply]
Neil (30 comments.) — 04/19/2008 @ 10:45 pmI’m not as familiar with php (and WordPress) as with c++, but why not just use a different name for your new $wp_query instance, say $my_query, and leave the existing one as is?
[Reply]
Carson (29 comments.) — 04/20/2008 @ 9:31 am@Carson - That’s what I’ve done in the past. I don’t really understand why you would need to use $wp_query, when you can use a different name. But it seems that everyone has a different way of doing it.
[Reply]
Darryl (6 comments.) — 04/20/2008 @ 10:02 am@Carson and Darryl,
Certain functions specifically call the $wp_query directly and don’t allow you to change the variable name. You can use $my_query, but for those functions that call $wp_query, they won’t work or, even worse, they will refer to the original $wp_query.
[Reply]
Aaron (33 comments.) — 04/20/2008 @ 12:35 pm@Aaron: I see. I understand that “the loop” is supposed to be a convenience for template builders. But for me it has been more like a millstone around my neck. Then I discovered that some (maybe all?) of the functions that only work in the loop have non-loop versions. I’m sure there is a reason for all this but I’ve found that when work-arounds abound there is usually an underlying design flaw. Let me add though that in my career as a coder I never had to satisfy millions of users — at most dozens.
[Reply]
Carson (29 comments.) — 04/20/2008 @ 1:21 pmThis was helpful, I have a bunch of static pages in the loop (I added WP on top of a mostly static site).
[Reply]
tinkertim (1 comments.) — 04/20/2008 @ 1:24 pm@Carson,
Yes, the loop functions typically use global variables and also call other non-loop functions. The issue here is paging, and using something other than wp_query (a global variable) will break paging.
The other article I wrote (mentioned at the very beginning) covers custom loops that don’t require paging.
[Reply]
Ronald Huereca (66 comments.) — 04/20/2008 @ 2:11 pm@Ronald: Your “how to” posts have been quite helpful. I have them all bookmarked. Thank you.
[Reply]
Carson (29 comments.) — 04/20/2008 @ 8:11 pm@Carson,
Thanks a lot! I hope they can help you out. If there’s anything else you’d like to know, please let me know. This post was written as a direct result of reader questions.
[Reply]
Ronald Huereca (66 comments.) — 04/20/2008 @ 9:56 pmNice post(s) on loops.
You can take this a step further and add a category tag to the query to loop category based posts into section to make widgets such as asides or side blogs.
In 2.3 and up you can use:
$wp_query->query('cat=X&showposts=5'.'&paged='.$paged);Where “X” is the number of the category of interest.
[Reply]
hso (8 comments.) — 04/20/2008 @ 10:41 pm@hso,
Yes, there are a very wide variety of applications. Using the query_posts parameters, and even filters, the possibilities seem endless.
Thanks for sharing your technique.
[Reply]
Ronald Huereca (66 comments.) — 04/20/2008 @ 11:01 pm[...] están pensando en agregar cositas nuevas a sus themes wordpress, acabo de ver este agradable tip para generar paginación con nuestros articulos [...]
Paginar artículos recientes en Wordpress « Xyberneticos — 04/21/2008 @ 3:19 am[...] Paging and Custom WordPress Loops (tags: wordpress) [...]
Skylog » Blog Archive » links for 2008-04-22 — 04/22/2008 @ 2:30 am[...] Paging and Custom WordPress Loops I stumbled on the right combination here by accident… useful info for anyone trying to deal with multiple “loops” (tags: linklog wordpress wp) [...]
Dancing Monkey Mania » Blog Archive » links for 2008-04-22 — 04/22/2008 @ 4:36 am[...] Paging and Custom WordPress Loops — I stumbled on the right combination here by accident… useful info for anyone trying to deal with multiple “loops” [...]
Ruminate » Blog Archive » Linklog: 2008-04-22 — 04/22/2008 @ 9:00 amI implemented your example code on my locally hosted test blog and found that it worked well except for one thing. When I click the More link it advances the actual recently posted articles as well as the new list of recently posted article titles. I looked at your implementation at raproject and saw that it doesn’t do this. Any idea why mine behaves that way?
[Reply]
Carson (29 comments.) — 04/22/2008 @ 11:40 am[...] Paging and Custom WordPress Loops - Za chví?u zo m?a bude programátor Ale ke? m?a to tak baví a skladanie kúskov kódov je ako Lego. No vždy treba ma? na pamäti, že profesionálne nasadenie si žiada profesionálny prístup. Amatérom sú pravidelne skryté na prvý poh?ad nevidite?né bezpe?nostné súvislosti. No a naopak, také to domácke programovanie je pre nás vedúcich projektov, zadávate?ov neocenite?né v jednej zásadnej oblasti. Vieme, že to ide zrealizova?. [...]
Do zákulisia celulózových výluhov a ?alší v rade : M+M+M+M (4M) — 04/23/2008 @ 10:45 am[...] Weblog Tools Collection pubblica un interessante post che illustra come integrare la paginazione nei loop di WordPress. [...]
Ultime dal fronte WordPress 17-2008 — 04/24/2008 @ 12:19 pm[...] Weblog Tools Collection made a great post that shows how to use pagination in the WordPress loops. [...]
WordPress Weekly News, 17-2008 — 04/25/2008 @ 5:04 am[...] están pensando en agregar cositas nuevas a sus themes wordpress, acabo de ver este agradable tip para generar paginación con nuestros articulos [...]
Extremisimo — 04/25/2008 @ 10:56 pmGreat stuff, just what I needed for a Wordpress project.
[Reply]
Paul @ Web Design Ireland (1 comments.) — 05/11/2008 @ 12:24 pmHow would you use this with an offset? For example ‘&offset=1′, so it doesn’t show the most recent 1 post. I tried usuing it as usual and it broke the navigation control
[Reply]
John Kolbert (23 comments.) — 05/13/2008 @ 1:38 am@John,
That’s odd. I haven’t tried an offset, but I know what you mean. Let me play around a bit and see if I can figure out what’s wrong.
[Reply]
Ronald Huereca (66 comments.) — 05/13/2008 @ 1:47 amThanks Ronald, I look forward to seeing what you can come up with!
[Reply]
John Kolbert (23 comments.) — 05/14/2008 @ 1:59 amThanks! I have been googling around for quite some time now looking for a way to do this! I’m surprised this information was so difficult to come by.
[Reply]
bnry (1 comments.) — 05/22/2008 @ 12:37 amThis is that I really looking for, thanks to make it Possible
[Reply]
IndoDX (1 comments.) — 05/29/2008 @ 8:27 pmThanks for the code tip.
However, if
$wp_query->query('cat=X&showposts=5'.'&paged='.$paged)will get me everything from category X, how do I modify it to get posts that are in both category X and category Y?[Reply]
Eric — 06/11/2008 @ 2:48 pmYou, sir, are a genius. I’d been trying to wrap my noob programmer head around multiple loops for a bit with code pulled from multiple templates; your solution pretty much fixed my problems. Thank you!
[Reply]
DC (1 comments.) — 06/30/2008 @ 11:39 amthanks. this worked for me. however, is there a way to have page numbers inserted in between the “<>” tags? much like what is done here: http://www.inquirer.net/specia.....rchive.php ?
[Reply]
venzie (1 comments.) — 07/2/2008 @ 12:53 pmI’m working on a three loop theme, and I’m trying my hardest to get the next_posts_link to rotate all three loops. It’s driving me mad, because I can get it to work for two out of three, but not the last loop.
Any ideas?
The code:
http://wordpress.pastebin.ca/1094042
[Reply]
@Dan,
I’m afraid not. I’ve never gotten paging to work on more than one loop since they all use the same global variable.
[Reply]
Ronald Huereca (66 comments.)August 6th, 2008 at 11:24 pm
I’m trying a lot of similar stuff to your more recent comments. I have a page I’m breaiking into two columns (using divs). One column shows the first 5 posts from a category, the other shows the next 5 (using offset). I wanted to know if this method of pagination will allow the next page to “pick up where I left off” and continue the two column format.
Otherwise… great code. It really helped in another situation.
[Reply]
don — 08/19/2008 @ 3:35 pmYou sir, are awesome! Thanks for the post!
[Reply]
John — 08/21/2008 @ 5:36 pmHeh. This works - but *only* if you’re using the default permalinks. I’ve been trying to figure this out since 2.1.x. I’ve just upgraded to 2.5.1, and I’m still having issues. I can do this - but only if I have “pretty permalinks” shut off.
Got any ideas why? (But thanks for the tut - I’m one step further than i was when I started!)
[Reply]
Shelly (1 comments.) — 08/22/2008 @ 9:50 amIt seems easier to just use the query_post call outside the loop while passing in the parameters including the paged. Seems to work just fine for me.
array(5,1), // fileter out categories
’showposts’ => 3, // limit post per page
‘paged’ => $paged, // allow for paging
‘year’=> $current_year,
‘monthnum’=>$current_month,
‘order’=>’DESC’, // sort by newest first
));
?>
[Reply]
charles — 09/12/2008 @ 4:19 pmDude! just what i needed
[Reply]
Peet — 09/26/2008 @ 11:59 amI feel really dumb right now… What is supposed to be defined in “$paged”? In my site it seems to be a blank variable.
Adam
[Reply]
adam — 10/5/2008 @ 2:52 pmHey there, this worked really well to resolve some basic pagination behavior - posts are now getting paginated properly… sort-of:
Pagination works once (eg. going from mydomain.com/news/ -to- mydomain.com/news/page/2). Going to page/3 however, results in a 404.
I tried to correct this in a number of ways by messing around with the query, but a bit of searching revealed that I’m not the only one experiencing this issue, and that no-one’s seemed to find a functional solution. The problem seems to arise when the blog uses a custom permalink structure, uses a static front-page, and has a custom wp_query in which showposts doesn’t agree with the default post display settings in ‘read’. Unfortunately, my entire reason for needing a custom query is to deal with paginated post lists of differing lengths on separate pages.
Any ideas? I’m tearing my hair out over this one
[Reply]
timichango — 10/13/2008 @ 7:59 am[...] Goel (@shantanugoel)for providing essential help and feedback, and to Ronald Huereca for writing an excellent guide on WordPress custom queries. Tags: free WordPress Theme, news, releases, Simple [...]
Download Simple Balance 2.1 Free WP Theme with Options Panel | Blogging Tips from Blogsessive — 10/26/2008 @ 7:44 pmThank you a lot Ronald!
I spend a lot time trying to get some sort of third type of terms worked into a wordpress installation (in addition to tags and categories) with custom fields. I would never have got it without your articles.
[Reply]
Kristof — 10/27/2008 @ 3:42 pmthanks for this, been looking for a solution to a multi loop setup and this works flawlessly…
[Reply]
CHANSON — 11/6/2008 @ 3:03 pmPerfect!!!
[Reply]
Jonas Ferreira (1 comments.) — 11/6/2008 @ 6:30 pmthanks so much for this blog post. The paging now works for my query.
[Reply]
aronil (1 comments.) — 11/23/2008 @ 7:27 am