I have custom post type called News and a static page that uses a custom template (page-news.php) and indexes all the news posts under homepage.com/news url.
The problem is that I want to paginate the news page so that homepage.com/news/page/2 would show more posts etc. but it returns a 404 error.
This is how I’m changing the pagination rules in functions.php:
function my_pagination_rewrite() {
add_rewrite_rule('page/?([0-9]{1,})/?$', 'page-news.php?category_name=blog&paged=$matches[1]', 'top');
}
add_action('init', 'my_pagination_rewrite');
And here is my custom query in the page-news.php:
<?php
$paged = ( get_query_var('paged') ) ? get_query_var( 'paged' ) : 1;
$query = new WP_Query(array(
'post_type' => 'news',
'post_status' => 'publish',
'posts_per_page' => '4',
'paged' => $paged
));
$temp_query = $wp_query;
$wp_query = NULL;
$wp_query = $query;
while ($query->have_posts()):
$query->the_post();
<!-- ECHOING THE NEWS POSTS-->
endwhile;
wp_reset_postdata();
echo '<div class="pagination">';
echo paginate_links( array(
'base' => str_replace( 999999999, '%#%', esc_url( get_pagenum_link( 999999999 ) ) ),
'total' => $query->max_num_pages,
'current' => max( 1, get_query_var( 'paged' ) ),
'format' => '?paged=%#%',
'show_all' => false,
'type' => 'plain',
'end_size' => 2,
'mid_size' => 1,
'prev_next' => true,
'prev_text' => sprintf( '<i></i> %1$s', __( 'Newer Posts', 'text-domain' ) ),
'next_text' => sprintf( '%1$s <i></i>', __( 'Older Posts', 'text-domain' ) ),
'add_args' => false,
'add_fragment' => '',
) );
echo '</div>';
$wp_query = NULL;
$wp_query = $temp_query;
?>
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
You don’t need the rewrite rules, and that’s not how they’d work anyway.
The fundamental problem is that you decided not to modify the main query, but to replace it.
There’s no need for the custom WP_Query or custom pagination, or a page template. Not to mention by running the main query then discarding the result to make a new one, it doubled the amount of work that needs doing, a major performance hit/slowdown
You can just use an archive-news.php template with a standard post loop, then use pre_get_posts to change how many posts are shown on the page:
// only show 4 posts per page on the news archive
add_action(
'pre_get_posts',
function( WP_Query $query ) {
// we only want the news post archive, exit early if it isn't
if ( ! $query->is_main_query() || ! $query->is_post_type_archive( 'news' ) ) {
return;
}
$query->set( 'posts_per_page', 4 );
}
);
Now the news archive will show 4 posts per page. No rewrite rules, no CPT adjustments, no special page with a page template for the pagination, it should all just work out the box with that hook. You can use normal standard main loops like the default themes. It’ll even be faster! You’re no longer doubling up all the queries by discarding the main query and putting your own in.
With that, your above code can be simplified to this in an archive-news.php template:
while ( have_posts() ) {
the_post();
<!-- ECHOING THE NEWS POSTS-->
}
echo '<div class="pagination">';
echo paginate_links();
echo '</div>';
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