最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

custom post types - Rewrite CPT slug with two taxonomy slug instead of one

programmeradmin1浏览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 -

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

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/3eLZhga2

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

Share Improve this question asked May 23, 2019 at 20:17 Asifur RahmanAsifur Rahman 52 bronze badges 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. – filipecsweb 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? – Asifur Rahman 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. – filipecsweb 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. – Asifur Rahman Commented May 27, 2019 at 21:07
Add a comment  | 

1 Answer 1

Reset to default 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/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/sector-chemical/service/post-slug
and would never match other URLs like:
http://example/blog/page/2.

发布评论

评论列表(0)

  1. 暂无评论