WordPress custom loop with pagination

if ( get_query_var('paged') ) {
	$paged = get_query_var('paged');
} elseif ( get_query_var('page') ) { // 'page' is used instead of 'paged' on Static Front Page
	$paged = get_query_var('page');
} else {
	$paged = 1;
$custom_query_args = array(
	'post_type' => 'post', 
	'posts_per_page' => get_option('posts_per_page'),
	'paged' => $paged,
	'post_status' => 'publish',
	'ignore_sticky_posts' => true,
	//'category_name' => 'custom-cat',
	'order' => 'DESC', // 'ASC'
	'orderby' => 'date' // modified | title | name | ID | rand
$custom_query = new WP_Query( $custom_query_args );
if ( $custom_query->have_posts() ) :
	while( $custom_query->have_posts() ) : $custom_query->the_post(); ?>
		<article <?php post_class(); ?>>
			<h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
			<small><?php the_time('F jS, Y') ?> by <?php the_author_posts_link() ?></small>
			<div><?php the_excerpt(); ?></div>
	<?php if ($custom_query->max_num_pages > 1) : // custom pagination  ?>
		$orig_query = $wp_query; // fix for pagination to work
		$wp_query = $custom_query;
		<nav class="prev-next-posts">
			<div class="prev-posts-link">
				<?php echo get_next_posts_link( 'Older Entries', $custom_query->max_num_pages ); ?>
			<div class="next-posts-link">
				<?php echo get_previous_posts_link( 'Newer Entries' ); ?>
		$wp_query = $orig_query; // fix for pagination to work
	<?php endif; ?>
	wp_reset_postdata(); // reset the query 
	echo '<p>'.__('Sorry, no posts matched your criteria.').'</p>';

WordPress query functions

  • query_posts() is overly simplistic and problematic way to modify main query of a page by replacing it with new instance of the query. It is inefficient (re-runs SQL queries) and will outright fail in some circumstances (especially often when dealing with posts pagination). Any modern WP code should use more reliable methods, like making use ofpre_get_posts hook, for this purpose. TL;DR don't use query_posts() ever;

  • get_posts() is very similar in usage and accepts same arguments (with some nuances, like different defaults), but returns array of posts, doesn't modify global variables and is safe to use anywhere;

  • WP_Query class powers both behind the scenes, but you can also create and work with own object of it. Bit more complex, less restrictions, also safe to use anywhere.

4 thoughts on “WordPress custom loop with pagination”

  1. The pagination is working for me partially. Unfortunately, it is only returning page one and two, when i try to exceed to order posts meaning to page three, it get stuck and repeats to page 2. Kindly assist me....


Leave a Comment