WordPress pagination: Simple and reuseable without a plugin

Pagination might be one of the most seen ui-patterns on the web. The concept of showing just a limited amount of articles, posts or whatever and making the reader click through the rest, comes in quite a few variations. Googles search results are coming to mind or more advanced infinite scroll solutions. Naturally, WordPress implements this concept and I have to admit that, for some time, I found it quite difficult to use, especially with custom queries.

As so often, the difficulties weren’t caused by the API-implementation or documentation, but myself not reading it. So, after realizing that, there was nothing left than working it out and here is the solution I use in my starter-theme. It contains a file named pagination.php, with the following content.

<?php 
     
     global $paginated_query;
     global $wp_query;

     if ( !$paginated_query ):
     	$paginated_query = $wp_query;
     endif;

     if ( $paginated_query->max_num_pages > 1 ) : ?>
          <div class="pagination">
              if ( !$current_page = get_query_var('paged') ) :
                  $current_page = 1;
              endif;

              echo paginate_links(array(
                  'base' => get_pagenum_link(1) . '%_%',
                  'current' => $current_page,
                  'total' => $total    
              )); ?>
          </div><?php
     endif;

?>

The great thing is, that the paginate_links function does all the page-logic for you, if you just provide it with a current page number and the total numbers of pages. So if you want to paginate your main loop, all you have to do, is to include this file. Since we don’t define a $paginated_query, the parameters will be taken from the global $wp_query.

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
...
<?php endwhile; endif; ?>
<?php get_template_part("pagination); ?>

But it’s quite easy, even with a custom query. Here you have to define the $paginated_query variable, before including pagination.php and giving the paged param to the WP_Query-object, so the requested page can be queried.

<?php 
    $custom_query = new WP_Query( array(
        'post_type' => 'page',
        'posts_per_page' => 3,
        'paged' => ( !$current_page = get_query_var('paged') ) ? 1 : $current_page
    ) );
?>
<?php if ( $custom_query->have_posts() ) : while ( $custom_query->have_posts() ) : $custom_query->the_post(); ?>
...
<?php endwhile; endif; ?>
<?php 
    $paginated_query = $custom_query;
    get_template_part("pagination); 
?>

That’s how I do it, but I’m always interested in other solutions.

Please comment if you have a better or alternative solution!