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 |1 Answer
Reset to default 1It 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.
- 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.
);
- 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
.
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