You want display posts of a given type ({post_type}) from category ({term})
and structure of link should looks like this:
{post_type} / category / {term}
To avoid collisions with links to pages and “blog” posts, expression can not
start with ([^/]+)
, but should contain slug of post type entered explicitly.
This means a separate rule for each custom post type.
$regex = '^news/category/(.+?)/?$';
For the above expression, the $redirect
should contain category_name
and post_type
parameters:
$redirect="index.php?category_name=$matches[1]&post_type=news";
And in case of a custom taxonomy (^news/custom_tax_slug/(.+?)/?$
):
$redirect="index.php?CUSTOM_TAX_SLUG=$matches[1]&taxonomy=CUSTOM_TAX_SLUG&post_type=news";
To handle pagination you need another rule, which is an extended version of the above one.
$regex = '^news/category/(.+?)/page/?([0-9]{1,})/?$';
$redirect="index.php?category_name=$matches[1]&post_type=news&paged=$matches[2]";
All together:
function category_cpt_rewrites()
{
add_rewrite_rule( '^news/category/(.+?)/page/?([0-9]{1,})/?$',
'index.php?category_name=$matches[1]&post_type=news&paged=$matches[2]',
'top'
);
add_rewrite_rule( '^news/category/(.+?)/?$',
'index.php?category_name=$matches[1]&post_type=news',
'top'
);
}
Or:
function category_cpt_rewrites()
{
$post_types = [ 'news' ];
foreach ( $post_types as $cpt )
{
add_rewrite_rule( '^'. $cpt .'/category/(.+?)/page/?([0-9]{1,})/?$',
'index.php?category_name=$matches[1]&post_type=". $cpt ."&paged=$matches[2]',
'top'
);
add_rewrite_rule( '^'. $cpt .'/category/(.+?)/?$',
'index.php?category_name=$matches[1]&post_type=" . $cpt,
"top'
);
}
}