Wordpress rewrite rules and pagination
If you are making larger Wordpress site at some point you will definitely come across custom rewrite rules configuration.
The tools (plugins)
I would suggest Rewrite Analyzer as it shows matched URL parts which is very convenient for debugging.
Prioritize pagination over Custom Post Type (CPT) slug
So you want to have clean URL structure for your CPT archive, so the list page has the same URL as single CPT pages slug prefix.
Here is the URLs structure I'm talking about:
/career
- page with CPT archive/career/page/2
- second page of CPT archive/career/some-position-offer
- single CPT page
Such URL structure requires defining a custom rewrite rule.
Out of the box Wordpress fail to route to the /career/page/2
, because before looking for the second page it will try to find CPT (named career
in this example) with page/2
slug. As a result the visitor will go to the 404 page instead of the second page for the Post archive.
It's quite easy to solve with add_rewrite_rule
function. Write following PHP code into your theme/plugin functions.php
file (or anywhere else where you store custom PHP code for Wordpress):
// functions.php
// prioritetize pagination over displaying custom post type content
add_action('init', function() {
add_rewrite_rule('(.?.+?)/page/?([0-9]{1,})/?$', 'index.php?pagename=$matches[1]&paged=$matches[2]', 'top');
});
If you do that the Wordpress will try to find next page before it tries to find the CPT single page.
For more info about add_rewrite_rule
check out the official documentation https://developer.wordpress.org/reference/functions/addrewriterule/.
Restricting selected slugs in Wordpress
Sometimes, especially when you start messing with the default URL structure there might be a necessity of restricting some slugs. Here is an example which will show how to prevent Post slug collisions with the existing Categories slugs functions.php
:
// functions.php
// Prevent category - post slug collisions
// Restrict selected slugs for posts
add_filter( 'wp_unique_post_slug', function( $slug, $post_ID, $post_status, $post_type ) {
if ( 'post' == $post_type ) {
$categories = get_categories();
$categories = array_map(function($c) { return $c->slug; }, $categories);
if ( in_array($slug, $categories) ) {
return $slug . '-' . $post_ID;
}
}
return $slug;
}, 10, 4 );
This code will append -[post_ID]
to the end of the Post slug if it happens to be same as on of the slugs for existing categories.
All examples are written for PHP >= 5.4.
Issues
Problems with pagination, rewrite rules and generally URL structure.
- Don't name query variable same as existing taxonomy slug. So if you have taxonomy with slug
company
avoid using?company=xyz
as a query variable. - If you want to change number of
posts_per_page
on default Wordpress post list page you should change this number not only inquery_args
array but also in Wordpress settings. In other case (if you change justquery_args
) you will get into troubles with pagination.