How to add term name to slug?
By default permalink of custom post type (CPT) has only slug of the post-type and title of the post. There are cases post type should be contain term names.
Problem: We have some CPT e.g. resource, it has slug resources/download-center and taxonomy resource_category. We should be, that this CPT has permalink /resources/term-name/post-title/ , also archive page /resources/.
Solution: Let's go step by step.
Step 1: In the function where we registered CPT instead 'rewrite' => [ 'slug' => 'resources/download-center' ]
write next 'rewrite' => [ 'slug' => 'resources/%cat%' ]
.
Step 2: In the function.php add code:
<?php
// Replace Slug From URL Post Type Resource
add_filter( 'post_type_link', 'replace_slug', 1, 3 );
function replace_slug( $post_link, $id = 0 ) {
$post = get_post( $id );
if( $post->post_type == 'resource' ) {
if ( is_object( $post ) ) {
$terms = wp_get_object_terms( $post->ID, ['resource_category'] );
if ( $terms ) {
return str_replace( '%cat%', $terms[0]->slug, $post_link );
}
}
}
return $post_link ;
}
add_action( 'init', 'generated_rewrite_rules' );
function generated_rewrite_rules() {
add_rewrite_rule(
'^resources/(.*)/(.*)/?$',
'index.php?post_type=resource&name=$matches[2]',
'top'
);
}
After then, go Setting — Permalinks — Save Changes. But if we go on /resources/ we'll see 404 page.
Step 3: Return to first step and replace 'has_archive' => true
to 'has_archive' => 'resources
. Ultimately, we have:
<?php
$args = [
...
'rewrite' => [ 'slug' => 'resources/%cat%' ]
'has_archive'=> 'resources',
...
]
Again go Setting — Permalinks — Save Changes.
Sources: