1

I have a custom post type of news_archive and they are using WordPress Categories. I would like to get some archive pages for these categories with only the CPTs and not core Posts. I managed to come across this url, which does exactly what I want when tied with my custom archive page:

/stories/category/in-the-news/?post_type=archived_news/

Where stories is the blog post permalink set in Custom Structure on the Permalinks page.

What I'd like to do is turn that into

/news/category/in-the-news/

where news is the rewrite for archived_news posts

I was trying something like:

function category_cpt_rewrites() {
    $categories = array( 'in-the-news', 'press-release' );
    foreach ( $categories as $category ) {
        $rule    = '/stories/category/' . $category . '/?post_type=archived_news';
        $rewrite = '/archived_news/category/' . $category . '/';
        add_rewrite_rule( $rule, $rewrite, 'top' );
    }
}

add_action( 'init', 'category_cpt_rewrites' );

But I don't think I have the syntax right. Do I even have the right idea?

*edit Ok I got it working, sort. Had to swap the rule/rewrite values and then use the correct regex.

function category_cpt_rewrites() {
    $categories = array( 'in-the-news', 'press-release' );
    foreach ( $categories as $category ) {
        $rule    = '^news/category/([^/]*)/?';
        $rewrite = 'index.php?post_type=archived_news&category=' . $category;
        add_rewrite_rule( $rule, $rewrite, 'top' );
    }
}

add_action( 'init', 'category_cpt_rewrites' );

I'm still getting both categories displaying, but I think I'm close. However, now pagination doesn't work and I'm not sure why. /news/category/press-release/page/2/ returns the same posts as the first page but /stories/category/press-release/page/2/?post_type=archived_news gives me the next page of posts

1

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'
        );
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.