URL generation issues w/ Custom Taxonomy on CPT
-
Hey everyone. So I’m struggling with a legacy theme I’m cleaning up some of the URL hierarchy on. And I’m hitting some dead ends and hoping that someone can help aim me in a better direction.
The Problem Statement
So I’ve got a CPT called ‘tours’. And I have a hierarchical custom taxonomy called destination. The idea is to end up with URLS that look like this:
/tours/europe/western-europe/france/14-day-french-extravaganza
Where the
/europe/western-europe/france
part is the custom taxonomy.It ‘feels’ like this should be simple and just work. Just setup the CPT and taxonomy, tell the tax that it’s hierarchical, and tell the CPT that it should use that taxonomy for an archive setup. But of course that simplicity doesn’t seem to work.
Where I am
Currently I have it working that if you go to:
/tours/europe
… you get all tours in europeAnd that the canonical URL of the tour in question is in fact:
/tours/europe/western-europe/france/14-day-french-extravaganza
The problem is everything in the middle.. If you go to
/tours/europe/western-europe
for example. It errors/404’s. Because my custom rewrites are telling it that obviouslywestern-europe
must be a post, not a tax. And that’s where I’m kinda stuck.So I’m hoping someone can point out either what I need to do (complex), or what the simple issue is that I’m running into.
Code
Here’s some sample code showing what I have right now:The Tax:
register_taxonomy( 'destination', 'tours', [ 'label' => __( 'Destination' ), 'rewrite' => [ 'slug' => 'tours', 'hierachical' => true, 'with_front' => false, ], 'public' => true, 'hierarchical' => true, 'show_in_nav_menus' => true, 'show_in_rest' => true, 'description' => 'All destinations that a tour goes to' ] );
The CPT:
register_post_type('tours', array ( 'labels' => array ( 'name' => 'Tours', 'singular_name' => 'Tour', 'add_new_item' => 'Add New Tour', 'edit_item' => 'Edit Tour', 'new_item' => 'New Tour', 'view_item' => 'View Tour', 'view_items' => 'View Tours', ), 'public' => true, 'exclude_from_search' => true, 'has_archive' => 'tours', 'capability_type' => 'page', 'rewrite' => array ( 'slug' => 'tours/%destination_tax%', 'with_front' => false, ), 'supports' => array ( 'title', 'editor', 'excerpt', 'trackbacks', 'custom-fields', 'revisions', 'thumbnail', 'author', 'page-attributes', ), 'show_in_rest' => true, 'hierarchical' => false, 'taxonomies' => array ( 'destination', ), 'menu_icon' => 'dashicons-location-alt', )
Custom post links setup, to build out the full canonical URLs:
function custom_post_links( string $post_link, \WP_Post $post, bool $leavename ): string { if ($post->post_type === 'tours') { // Using yoast primary term feature $termID = \yoast_get_primary_term_id('destination', $post); $destinationURL = wpterm_build_hierarchy($termID); return str_replace('%destination_tax%', $destinationURL, $post_link); } } add_filter( 'post_type_link', 'custom_post_links', 10, 3 );
function wpterm_build_hierarchy($termID, $result = "") { if ($termID) { $term = \get_term($termID); if ($term && !is_wp_error($term)) { return wpterm_build_hierarchy($term->parent, $term->slug . '/' . $result); } } return trim($result, '/'); }
And the custom rewrite rule for the full URL:
function custom_rewrite_rules() { // Handle rewriting our tour pages w/ taxonomy: $terms = get_terms([ 'taxonomy' => 'destination', 'hide_empty' => true, ]); if (!empty($terms) && !is_wp_error($terms)) { $slugs = []; foreach ($terms as $term) { $slugs[] = $term->slug; } $sluggos = implode('|', $slugs); add_rewrite_rule( "^tours/(?:(?:{$sluggos})/)*([^/]*)$", 'index.php?post_type=tours&name=$matches[1]', 'bottom'); } } add_action('init', 'custom_rewrite_rules');
- You must be logged in to reply to this topic.