Pagination Doesn’t Work

I created myfile.php with the following content:

global $paged;
if ( get_query_var( 'paged' ) ) {
    $paged = get_query_var( 'paged' );
} else if ( get_query_var( 'page' ) ) {
    $paged = get_query_var( 'page' );
} else {
    $paged = 1;
}

$args = array(
    'post_type' => array('my_custom_post_type'),
    'paged' => $paged,
    'posts_per_page' => 3,
    'ignore_sticky_posts' => 1
);

$wp_query = new WP_Query( $args );
var_dump($wp_query);
if($wp_query->have_posts()) :
    while($wp_query->have_posts()) : $wp_query->the_post();
        // show post
    endwhile;
endif;

next_posts_link('Next posts');

wp_reset_query();
wp_reset_postdata();

and:

Read More

I have no idea what am I missing here but I just tried every single suggestion from troubleshooting guide on this page: https://codex.wordpress.org/Pagination – they suggest that “404 – not found” is one of the common problems when the permalinks are set to “Custom Structure” so WP developers are aware of some bug or issue but they don’t say how to fix that.

My server is WAMP for Windows 7 (PHP 5.4.3, Apache 2.4.2, mod_rewrite enabled, custom link structures work great expect pagination when “myfile.php” is used as a page other than “Static Front Page”).

My .htaccess when “Custom Permalink Structure” is set to “Post name”:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wp/index.php [L]
</IfModule>

# END WordPress

When I enter http://example.com/mypage/page/2 (doesn’t work): SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.post_name = 'page' AND wp_posts.post_type = 'my_custom_post_type' ORDER BY wp_posts.post_date DESC

When I enter http://example.com/?page_id=1234&paged=2 (works): SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'my_custom_post_type' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 2, 2

Related posts

3 comments

  1. I’ve experienced this with several plugins of my own, while trying to display a numerical pagination for my custom post types and custom taxonomies.

    It’s my understanding that by using WP_Query to fetch posts from the database in your own custom way (other than the default) will prevent you from using such functions as expected.

    They’re intended to be used for the default posts query. So if you would like to use those functions as intended, then you’ll need to modify the default query BEFORE the query is performed. You can do this using the hook pre_get_posts.

    However, if you would like to use your own custom query using WP_Query, then you’ll need to also customize how the numerical pagination works. You can get the same net result using standard WordPress functionality, but it requires a few extra lines of code to achieve the numerical pagination as expected.

    Let’s say you have a custom query using WP_Query and it looks something like this:

    $query = new WP_Query( $query_args );

    This means you have a completely BRAND NEW query which is different than the main default query which is performed when the page is loaded.

    Now WordPress is aware of TWO queries for the current page:

    1. Query #1 being the default query.
    2. Query #2 being your custom query you just created using WP_Query.

    If you want your numerical pagination to work with your custom query, then you need to be aware of the current page the request is performed on.

    The current page number is actually referred to as paged. You can determine the current page number using some code like this:

    $current_page = 1;
    
    if ( get_query_var( 'paged' ) ) {
        $current_page = get_query_var( 'paged' );
    }
    

    Once the current page has been determined, you can setup your custom query to look similar to this:

    $query_args = array(
        'post_type'      => 'products',
        'post_status'    => 'publish',
        'posts_per_page' => 10,
        'paged'          => absint( $current_page )
    );
    
    $query = new WP_Query( $query_args );
    

    Once the query has been performed, you then need to check if it’s located any posts in the database which match your criteria:

    if ( $query->have_posts() ) {
    
        while ( $query->have_posts() ) {
    
            $query->the_post();
    
            // Post content here...
    
        }
    
    } else {
    
        // No posts...
    
    }
    

    Now for the numerical pagination! I recommend using a WordPress function called paginate_links() for this part.

    I don’t really understand the really unlikely integer part for the base, but that’s what’s demonstrated on the WordPress Codex page linked above.

    • You need to specify the current page (paged) — once again.
    • You need to know the total number of posts (which can be obtained
      from the $query variable object).
    • You need to specify a return type for this function. (Personally, I
      like it to be in array format, so that I can customize the pagination
      however I see fit).

    $big = 999999999; // need an unlikely integer
    
    $previous_text = '&laquo; Previous';
    $next_text     = 'Next &raquo;';
    
    $pagination = paginate_links( array(
        'base'      => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
        'format'    => '?current_page=%#%',
        'current'   => max( 1, $current_page ),
        'total'     => $query->max_num_pages,
        'type'      => 'array',
        'prev_text' => $previous_text,
        'next_text' => $next_text
    ) );
    

    This code needs to be placed within the condition which states that we have posts available. Not inside the loop, but immediately AFTER the loop.

    Once the numerical pagination has been configured, it’s ready for output (or ready to be displayed). This is where paginated items are returned in array format.

    I like to wrap it with a conditional check and then loop through the items performing additional conditional checks along the way.

    if ( $pagination ) {
    
        $content .= '<div class="clearfix"></div>' . PHP_EOL;
        $content .= '<nav id="numerical-pagination" class="text-center">' . PHP_EOL;
        $content .= '<ul class="pagination">' . PHP_EOL;
    
        foreach ( $pagination as $pagination_item ) {
    
            $class = '';
    
            if ( stripos( $pagination_item, 'current' ) !== false ) {
                $class = ' class="active"';
            }
    
            if ( stripos( $pagination_item, 'dots' ) !== false ) {
                $class = ' class="disabled"';
            }
    
            $content .= '<li' . $class . '>' . $pagination_item . '</li>' . PHP_EOL;
    
        }
    
        $content .= '</ul>' . PHP_EOL;
        $content .= '</nav><!-- end #numerical-pagination .text-center -->' . PHP_EOL;
        $content .= '<div class="clearfix"></div>' . PHP_EOL;
    
        echo $content;
    
    }
    

    Note: I use Bootstrap for my WordPress themes. So if you want your pagination to look awesome, with minimal effort involved. Try out Bootstrap.

    To conclude everything mention above, here’s a all-in-one copy/paste starter solution for anyone looking to create a numerical pagination with a custom posts query using WP_Query.

    $current_page = 1;
    
    if ( get_query_var( 'paged' ) ) {
        $current_page = get_query_var( 'paged' );
    }
    
    $query_args = array(
        'post_type'      => 'products',
        'post_status'    => 'publish',
        'posts_per_page' => 10,
        'paged'          => absint( $current_page )
    );
    
    $query = new WP_Query( $query_args );
    
    if ( $query->have_posts() ) {
    
        while ( $query->have_posts() ) {
    
            $query->the_post();
    
            // Post content here...
    
        }
    
        $big = 999999999; // need an unlikely integer
    
        $previous_text = '&laquo; Previous';
        $next_text     = 'Next &raquo;';
    
        $pagination = paginate_links( array(
            'base'      => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
            'format'    => '?current_page=%#%',
            'current'   => max( 1, $current_page ),
            'total'     => $query->max_num_pages,
            'type'      => 'array',
            'prev_text' => $previous_text,
            'next_text' => $next_text
        ) );
    
        $content = '';
    
        if ( $pagination ) {
    
            $content .= '<div class="clearfix"></div>' . PHP_EOL;
            $content .= '<nav id="numerical-pagination" class="text-center">' . PHP_EOL;
            $content .= '<ul class="pagination">' . PHP_EOL;
    
            foreach ( $pagination as $pagination_item ) {
    
                $class = '';
    
                if ( stripos( $pagination_item, 'current' ) !== false ) {
                    $class = ' class="active"';
                }
    
                if ( stripos( $pagination_item, 'dots' ) !== false ) {
                    $class = ' class="disabled"';
                }
    
                $content .= '<li' . $class . '>' . $pagination_item . '</li>' . PHP_EOL;
    
            }
    
            $content .= '</ul>' . PHP_EOL;
            $content .= '</nav><!-- end #numerical-pagination .text-center -->' . PHP_EOL;
            $content .= '<div class="clearfix"></div>' . PHP_EOL;
    
            echo $content;
    
        }
    
        wp_reset_postdata();
    
    } else {
        // No posts...
    }
    
    wp_reset_query();
    
  2. You can also try below code.

    function custom_type_archive_display($query) {
    
        if (is_post_type_archive('custom_post_type') )
        {
            $query->set('posts_per_page',10);
            return;
        }
    }
    
    add_action('pre_get_posts', 'custom_type_archive_display');
    
  3. After hours of struggling I found the cause.

    The post type that I registered using register_post_type( 'my_custom_post_type', array( ... ) ); had 'rewrite' => array( 'slug' => 'my_custom_post_type' ). That was taking priority over pagination and that’s why “404 – not found” was happening.

    If anyone has better explanation of what takes priority and when, please edit my answer. This issue is resolved after editing rewrite to something else.

Comments are closed.