Paginate Custom Post Type Page

The question:

I created a page for my custom post types. The code can be viewed on Snippi: http://snippi.com/s/e8852rx

I’m trying to insert paginate_links, but for whatever reason it’s simply not showing up. Here is the paginate_links code (this code works on normal archive.php files):

<?php
global $wp_query;

$big = 999999999; // need an unlikely integer

echo paginate_links( array(
    'base' => str_replace( $big, '%#%', get_pagenum_link( $big ) ),
    'format' => '?paged=%#%',
    'current' => max( 1, get_query_var('paged') ),
    'total' => $wp_query->max_num_pages
) );
?>

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

The following works for me (I’ve removed all the formating / custom post meta).

I would add, its not clear why you need to use a page with a custom template, and don’t instead create a template called archive-portfolio.php which is used for a custom post type’s archive pages (see template hierarchy)

<?php
/*
Template Name: Portfolio
*/
?>

<?php get_header(); ?>
<div id="container">
<div id="portfolio_content">
<div id="portfolio_wrap">

    <?php $loop = new WP_Query(array('post_type' => 'portfolio', 'posts_per_page' => get_option('to_count_portfolio'), 'paged' => get_query_var('paged') ? get_query_var('paged') : 1 )
); ?>
    <?php while ( $loop->have_posts() ) : $loop->the_post(); ?>
        <span class="title"><?php the_title(); ?></span></br>
        <?php endwhile; ?>  

<?php

$big = 999999999; // need an unlikely integer
 echo paginate_links( array(
    'base' => str_replace( $big, '%#%', get_pagenum_link( $big ) ),
    'format' => '?paged=%#%',
    'current' => max( 1, get_query_var('paged') ),
    'total' => $loop->max_num_pages
) );
?>
</div>
</div>
</div>
</div>

<?php get_footer(); ?>

Method 2

Instead of using the “$loop->have_posts()” approach, like Stephen Harris pointed, you can also try looping the posts like this:

<?php foreach ($loop->get_posts() as $post) { ?>
     <span class="title"><?php echo $post->post_title; ?></span></br>
<?php } ?>

Method 3

Have you tried using the portfolio post type root archive page?

If you move most of your code into an archive-portfolio.php file, then the loop should be setup correctly and paging should work out of the box, with no funky functions, or hacks or kludges, just like it does on post archives.

It also means you don’t need to use you’re own custom query, just use the main loop instead, making the page load faster

Method 4

You are refernecing the main query, so it’s likely that it’s trying to show ‘posts’ only, as opposed to your custom post type.

Not sure what your exact format is, but I’d redo the query so –

$args = Array( // Array of arguments for query_posts()
    'numberposts' => -1,
    'posts_per_page' => get_option('posts_per_page'),
    'paged' => $paged,
    'post_type' => array('your-post-type-slug', 'another-post-type-slug-if-you-want')
);
query_posts($args);

This means that your code would become –

<?php
global $wp_query; // You don't need this if you are not in a function, so can probably be removed.

$args = Array( // Array of arguments for query_posts()
    'numberposts' => -1,
    'posts_per_page' => get_option('posts_per_page'),
    'paged' => $paged,
    'post_type' => array('your-post-type-slug', 'another-post-type-slug-if-you-want')
);
query_posts($args);


$big = 999999999; // need an unlikely integer

echo paginate_links( array(
    'base' => str_replace( $big, '%#%', get_pagenum_link( $big ) ),
    'format' => '?paged=%#%',
    'current' => max( 1, get_query_var('paged') ),
    'total' => $wp_query->max_num_pages )
);
?>

Method 5

This is a problem I have struggled with on plenty of occasions.

Here’s what has worked for me in this situation (WP 3.1.1):

<?php   
                $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
                $args = array( 'post_type' => 'custom_post_type', 'posts_per_page' => 5, 'paged' => $paged);
                $loop = new WP_Query( $args );
                if($loop->have_posts()):
                    while ( $loop->have_posts() ) : $loop->the_post();
                        //whatever output you require, such as, e.g:
                        the_excerpt();
                    endwhile;
                endif;
        ?>

Then, for the pagination controls:

<?php 
    echo custom_paginate_links( 
                            array(
                                'format' => '?paged=%#%',
                                'current' => max( 1, get_query_var( 'paged' ) ),
                                'total' => $loop->max_num_pages
                                ) );
?>

Method 6

It would be better to create a function within your functions.php file that handles pagination and can be used throughout your theme, for standard, and custom post types.

With the following function dropping get_pagination() into your theme will give you navigation where-ever you need it. I wrote a blog post on it here: http://deadlyhifi.com/2011/06/non-bloated-pagination-for-your-wordpress-functions-php-file/ (and the code is based on http://robertbasic.com/blog/wordpress-paging-navigation/ originally)

/**
 * A pagination function
 * @param integer $range: The range of the slider, works best with even numbers
 * Used WP functions:
 * get_pagenum_link($i) - creates the link, e.g. http://site.com/page/4
 * previous_posts_link(' ‚ '); - returns the Previous page link
 * next_posts_link(' é '); - returns the Next page link
 * http://robertbasic.com/blog/wordpress-paging-navigation/
 * tweaked by tdB ...
 */
function get_pagination($range = 4) {
global $paged, $wp_query;

// How much pages do we have?
if ( !$max_page ) {
    $max_page = $wp_query->max_num_pages;
}

// We need the pagination only if there is more than 1 page
if ( $max_page > 1 ) {
    if ( !$paged ) $paged = 1;

    echo '<div class="postpagination">';

    // To the previous page
    previous_posts_link('Prev');

    if ( $paged >= $range ) echo '<a href="' . get_pagenum_link(1) . '" rel="nofollow noreferrer noopener">1</a>';
    if ( $paged >= ($range + 1) ) echo '<span class="page-numbers">&hellip;</span>';

    // We need the sliding effect only if there are more pages than is the sliding range
    if ( $max_page > $range ) {
        // When closer to the beginning
        if ( $paged < $range ) {
            for ( $i = 1; $i <= ($range + 1); $i++ ) {
                    echo ( $i != $paged ) ? '<a href="' . get_pagenum_link($i) .'" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener">'.$i.'</a>' : '<span class="this-page">'.$i.'</span>';
            }
        // When closer to the end
        } elseif ( $paged >= ($max_page - ceil(($range/2))) ) {
            for ( $i = $max_page - $range; $i <= $max_page; $i++ ) {
                echo ( $i != $paged ) ? '<a href="' . get_pagenum_link($i) .'" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener">'.$i.'</a>' : '<span class="this-page">'.$i.'</span>';
            }
        // Somewhere in the middle
        } elseif ( $paged >= $range && $paged < ($max_page - ceil(($range/2))) ) {
            for ( $i = ($paged - ceil($range/2)); $i <= ($paged + ceil(($range/2))); $i++ ) {
                echo ($i != $paged) ? '<a href="' . get_pagenum_link($i) .'" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener">'.$i.'</a>' : '<span class="this-page">'.$i.'</span>';
            }
        }
    // Less pages than the range, no sliding effect needed
    } else {
        for ( $i = 1; $i <= $max_page; $i++ ) {
                echo ($i != $paged) ? '<a href="' . get_pagenum_link($i) .'" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener">'.$i.'</a>' : '<span class="this-page">'.$i.'</span>';
            }
    }

    // On the last page, don't put the Last page link
    if ( $paged <= $max_page - ($range - 1) ) echo '<span class="page-numbers">&hellip;</span><a href="' . get_pagenum_link($max_page) . '" rel="nofollow noreferrer noopener">' . $max_page . '</a>';

    // Next page
    next_posts_link('Next');

    echo '</div><!-- postpagination -->';
}
}

Method 7

I’ve never had a problem using pagination on a custom archive.
So, instead of making a page and then writing my own query on it, just copy/paste archive.php and rename it match your custom post, eg archive-videos.php.

If you really want to use custom page template, add this just before your query:

query_posts( array( 'post_type' => 'videos', 'paged' => get_query_var('page') ) )

More info: http://scribu.net/wordpress/wp-pagenavi/right-way-to-use-query_posts.html


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment