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!

	function my_related_posts_thumbnail( $title, $post, $instance ) {
		if ( has_post_thumbnail( $post->ID ) ) {
			$title = get_the_post_thumbnail($post->ID).$title;
		}
		return $title;
	}
	add_filter( 'simply_related_posts_title', 'my_related_posts_thumbnail', 10, 3 );

The Snippets Story

If you are using my Simply related Posts plugin, you might want to have related post thumbnails. The code above is simply adding the post-thumbnail before the related post titles, if it exists. It implements the simply_related_posts_title filter, to add thumbnails to the printed title. Of course, you can add not only thumbnails, but any other kind of information to the title, by using that filter.

Works with version Simply related Posts 1.2 and later.

function check_custom_query_param( $query ) {
    if ( isset($query->query_vars['custom_param']) && $query->query_vars['custom_param']) {
        $query->custom_param = true;
    }
}
add_action( 'pre_get_posts', 'check_custom_query_param' );


function change_where_query( $where, &$wp_query ) {
    global $wpdb;	
    if ( property_exists ( $wp_query , 'custom_query' ) && $wp_query->custom_query ) {
    	// change the where query
    }
    return $where;
}
add_filter('posts_where', 'change_where_query', 10, 2);

The snippets story

Some weeks ago I wanted to pass a custom parameter to the WP_Query object to change the where-query if the param was true. The problem was, that to extend WP_Query with a parameter, you have to circumvent the filtering of the query options. I solved this by hooking into the pre_get_posts action. There the custom parameter is still available and we can easily add it to the filtered query object.