0

I have a post type location with 2 taxonomies in it - service & sector. Now, normally wordpress would show the permalink like - site_url/location/post_name I've made it work to show - site_url/service_slug/sector_slug/post_name

This is exactly how I want it and I've achieved it. Problem is, it broke all the page url's! Example: I have contact page which is siteurl/contact. Now it's showing 404 when I go to the contact page url. Meaning the permalink structure works ok with my location post type but it broke all my page permalinks.

I've updated wordpress permalink structure to /%postname%/ several times.

Here's my code below -

Location post type rewrite slug -

'rewrite' = array(
    'slug' => '%sector%/%service%',
    'with_front' => true
);

*I've tried 'with_front' false too, same thing.

Custom function to update slug -

function rewrite_location_post_slug( $post_link, $id = 0 ){
$post = get_post($id);  
if ($post->post_type == 'location'){
    $terms_service = wp_get_object_terms( $post->ID, 'service' );
    $terms_sector = wp_get_object_terms( $post->ID, 'sector' );
    if( $terms_service && $terms_sector){
        $sector_replaced = str_replace( '%sector%' , $terms_sector[0]->slug , $post_link );
        return str_replace( '%service%' , $terms_service[0]->slug , $sector_replaced );
    }
} else {
return $post_link; 
}   
}
add_filter( 'post_type_link', 'rewrite_location_post_slug', 1, 3 );

Taxonomies don't have any rewrite slug in their code. Full code here - https://pastebin.com/3eLZhga2

Is this a wordpress bug or am I missing something? Please advise.

4
  • I can make it work for you as long as your service_slug and/or your sector_slug have, for instance, a prefix or suffix. E.g. service-repair. Did you get it? Would it break your strategy? The thing here is we need a standard to correctly create the pattern for the rewrite rule. The way you want it you have no standard, like a "fake pattern", which would look like: ([^/]+)/([^/]+)/([^/]+)/?. It could work, I'd have to test, but it could also break things without you knowing it. Commented May 27, 2019 at 20:33
  • I can't work with a prefix or suffix that's why I had to find a different solution, like internal forwarding.... Is this a wordpress bug? shouldn't wordpress allow it by default? Commented May 27, 2019 at 20:36
  • It's allowed, but that pattern would match any URL which has 3 resources/components. Maybe your theme or a plugin has already registered it, maybe not. Anyway, I'll sleep on it. Commented May 27, 2019 at 20:59
  • I tried it with wp default themes with totally new sites. Same issue. Thank you for helping out. Commented May 27, 2019 at 21:07

1 Answer 1

1

It seems WordPress breaks other rewrite rules when you use the character % for rewrite slug of CPTs. Not sure why.

Anyway, I got it to work making the following changes in your code.

  1. Stop using %. It's not required actually:
$rewrite = array(
    'slug'       => 'sector/service',
    'with_front' => false // It has nothing to due with the solution, but you'd better put false here.
);
  1. Replace /sector/ and /service/ instead of %sector% and %service%:
function rewrite_location_post_slug( $post_link, $post ) {
    if ( $post->post_type == 'location' ) {
        $terms_service = wp_get_object_terms( $post->ID, 'service' );
        $terms_sector  = wp_get_object_terms( $post->ID, 'sector' );
        if ( $terms_service && $terms_sector ) {
            $sector_replaced = str_replace( '/sector/', "/{$terms_sector[0]->slug}/", $post_link );

            return str_replace( '/service/', "/{$terms_service[0]->slug}/", $sector_replaced );
        }
    }

    return $post_link;
}

add_filter( 'post_type_link', 'rewrite_location_post_slug', 1, 2 );

So far so good. Now, if you flush your permalinks you'll see that your contact page is back, but your site_url/sector/service/location/ is gone. That relates to the missing %, so we have to add that custom rewrite rule we talked about in the comments, which is actually dangerous as it's kind of a "fake pattern":

function rewrite_sector_service_location_url() {
    add_rewrite_rule( '^([^/]+)/([^/]+)/([^/]+)/?', 'index.php?location=$matches[3]', 'top' );
}

add_action( 'init', 'rewrite_sector_service_location_url' );

Flush your rewrite rules and you'll see that now everything works.

It should work for you, but I'd recommend you to use a prefix for your sectors and/or services, so we could add a standard to our rewrite pattern.

[EDIT]

I'll try to explain the solution if you chose adding prefixes to your terms.

Assume you chose the prefix sector to be given to all terms from the taxonomy sector.

So if you had 2 terms: Chemical and Construction, their slugs by default would be chemical and construction. But following that prefix rule their slugs should be changed to sector-chemical and sector-construction, respectively. Btw, WordPress has a filter (https://developer.wordpress.org/reference/hooks/pre_insert_term/) which you could use to add the prefix automatically.

Using that prefix standard our rewrite rule should be changed to:

function rewrite_sector_service_location_url() {
    add_rewrite_rule( '^(sector-[^/]+)/([^/]+)/([^/]+)/?', 'index.php?location=$matches[3]', 'top' );
}

add_action( 'init', 'rewrite_sector_service_location_url' );

The rule above makes sure we would match something like
http://example.com/sector-chemical/service/post-slug
and would never match other URLs like:
http://example.com/blog/page/2.

6
  • In case it is not too much trouble for you it would be great you can add the prefix solution to your answer as well! It might be very useful for other ( including me in future maybe ) :)
    – Luckyfella
    Commented May 28, 2019 at 7:04
  • @Luckyfella Sure, I will. Commented May 28, 2019 at 13:26
  • @filipecsweb hey thank you for your answer. I don't have way too many sectors. Around 10/11. So I am thinking about specifying the sector name in add_rewrite_rule. Also thinking about another solution, as it's a taxonomy term, I can just use foreach to make rewrite rule for every sector. Commented May 29, 2019 at 14:10
  • @AsifurRahman Yeah, you could. Not so elegant, but it would work. Later I will add a complement to my answer explaining the idea about prefixing. I reckon it would suit you better. Commented May 29, 2019 at 14:16
  • @Luckyfella just added the prefix solution. Commented May 29, 2019 at 15:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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