0

I'm rebuilding a site in which I am required to change the URL structure for archive pages to something that WordPress doesn't handle by default. I have a custom post type named product, which has a custom taxonomy product-category. I need to rewrite the /product-category/{term-slug} archive pages for this taxonomy to just be /{term-slug}.

So I am trying to make a rewrite rule that catches /{term-slug} pages, and rewrites them to /product-category/{term-slug}, ONLY if no other rules were matched.

I can do this to catch and rewrite these pages correctly:

function rewrite_product_archive() {
    add_rewrite_tag('%product-category%', '([a-z0-9\-_]+)');
    add_rewrite_rule(
        '^([a-z0-9\-_]+)/?$',
        'index.php?product-category=$matches[1]',
        'top'
    );
}
add_action('init', 'rewrite_product_archive');

With this, I can navigate to a /{term-slug} page and it will show the archive /product-category/{term-slug} page correctly. However, this now causes all actual pages to stop working and 404.

So I tried changing the third parameter in my rewrite from top to bottom, and doing a flush. This now makes my regular pages work again, but now the /{term-slug} rewrites have stopped working and they 404 now.

So essentially, I just need to follow the rewrite ONLY if no other rules were matched. Is that possible?

2
  • That's what you get if the rule comes last in the list, are you sure your rule actually matches the URL though? Have you confirmed this with a debug plugiin such as monkeyman rewrite rule analyser? – Tom J Nowell Oct 1 '20 at 16:05
  • @TomJNowell I figured it out. See my answer. – chrispytoes Oct 1 '20 at 17:40
0

It turns out it was because the default category archive pages do not require the URL to start with /category. WordPress already matches the path /{category-slug} for the default category taxonomy archive.

I fixed it by changing the default category archive rewrite to start with /category.

function move_category_rule($rules) {
    if(array_key_exists('(.+?)/?$', $rules)) {
        $val = $rules['(.+?)/?$'];
        unset($rules['(.+?)/?$']);
        $rules['category/(.+?)/?$'] = $val;
    }
    return $rules;
}
add_filter('rewrite_rules_array', 'move_category_rule');

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.