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/news url.
The problem is that I want to paginate the news page so that homepage/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;
?>
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/news url.
The problem is that I want to paginate the news page so that homepage/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;
?>
Share
Improve this question
asked Aug 5, 2020 at 15:50
Em KarimifarEm Karimifar
52 bronze badges
2
|
1 Answer
Reset to default 1You 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>';
index.php
. WP rewrite rules aren't like Apache or Nginx rules, they're just a regex mapping of pretty URLs on to query variables onindex.php
( the same query variables thatWP_Query
uses ). Also thatindex.php
is not theindex.php
in your theme, it's theindex.php
at the root of the WP site, but for rewrite rules it's just a formality, it is alwaysindex.php?param=value&etc...
– Tom J Nowell ♦ Commented Aug 5, 2020 at 16:06news
CPT that it had a permalinks front ofpage/
then used thearchive-news.php
, and all the pagination would have just worked out of the box with a standard post loop, with sitemaps and RSS feeds etc too if you wanted them – Tom J Nowell ♦ Commented Aug 5, 2020 at 16:09