I have the following requirements for url patterns:
/CPT/
(archive of custom post type)/CPT/post-name
(single post in custom post type)/CPT/category-name
(archive of cpt category)/CPT/category-name/post-name
(single post in custom post type category)
Those are the structures I need. So far 1, 3, and 4 are working properly - but I cannot get 2 to do anything but throw a 404.
When I modify the rewrite rules to accommodate #2, 3 or 4 breaks and either throws 404 or redirects to the home page. Is this possible to correct so all four permalinks are functional?
I tried using the CPT permalinks plugin - but I was unsuccessful at getting the /CPT/post-name
to work in conjunction with the other permalink structures I need (3 & 4).
I read through and attempted the use of another solution here - but again, these ignored the need for the structure of /cpt/post-name
.
Basically, I need to ensure that the slug for the custom post type and the slug for the custom post type custom category is the same - here are some specific examples of meaningful urls:
/services
(archive of custom post type)/services/botox
(single post of custom post type)/services/injectables
(archive of custom post type custom taxonomy)/services/injectables/botox
(single post of custom post type custom taxonomy)
Below is the code I currently have in place that is working with the exception of #2 structure:
// Register the Custom Post Type
function register_custom_post_type() {
$args = array(
'labels' => array(
'name' => 'Services',
'singular_name' => 'Service',
),
'public' => true,
'has_archive' => true,
'rewrite' => array(
'slug' => 'services', // Base slug for your CPT
'with_front' => false,
'hierarchical' => true, // Allows for /services/category/post
),
'show_in_rest' => true, // Enable Gutenberg editor if needed
'supports' => array( 'title', 'editor', 'excerpt', 'author', 'thumbnail', 'comments', 'revisions', 'custom-fields' ),
'taxonomies' => array('services_category'), // Attach custom taxonomy if needed
);
register_post_type('services', $args);
}
add_action('init', 'register_custom_post_type');
// Register Custom Taxonomy for the Custom Post Type
function register_custom_taxonomy() {
$args = array(
'labels' => array(
'name' => 'Services Categories',
'singular_name' => 'Services Category',
),
'public' => true,
'rewrite' => array(
'slug' => 'services', // This will make the taxonomy appear under /services/category-name/
'with_front' => false,
'hierarchical' => true, // Ensure categories are hierarchical (like regular categories)
),
'hierarchical' => true,
);
register_taxonomy('services_category', 'services', $args);
}
add_action('init', 'register_custom_taxonomy');
**// Custom Rewrite Rules to Match the Permalink Structure
function custom_rewrite_rules($rules) {
$new_rules = array(
// CPT Archive: /services/
'services/?$' => 'index.php?post_type=services',
// Single CPT Post: /services/post-name/
'services/([^/]+)/?$' => 'index.php?post_type=services&name=$matches[1]',
// Custom Taxonomy Archive: /services/category-name/
// This rule should be placed *after* the CPT single post rule to avoid conflicts
'services/([^/]+)/?$' => 'index.php?taxonomy=services_category&term=$matches[1]',
// Single CPT Post within a Category: /services/category-name/post-name/
'services/([^/]+)/([^/]+)/?$' => 'index.php?post_type=services&services_category=$matches[1]&name=$matches[2]',
);
return $new_rules + $rules;
}
add_filter('rewrite_rules_array', 'custom_rewrite_rules');
// Add rewrite tag for custom taxonomy (to ensure taxonomy permalinks work)
function add_custom_rewrite_tags() {
add_rewrite_tag('%services_category%', '([^&]+)');
}
add_action('init', 'add_custom_rewrite_tags');