Add parent/child taxonomy to custom post type url

I have seen several cases of one taxonomy being added to a custom post type url, but I have modified that function to include a parent and a child taxonomy term. However, I am getting a 404 when I go to the post page.

The custom post type is commercial and the taxonomy is commercial_taxonomies with a parent term of solar and child of neutral

function cptui_register_my_taxes() {

    /**
     * Taxonomy: Commercial Categories.
     */

    $labels = array(
        "name" => __( "Commercial Categories", "" ),
        "singular_name" => __( "Commercial Category", "" ),
    );

    $args = array(
        "label" => __( "Commercial Categories", "" ),
        "labels" => $labels,
        "public" => true,
        "hierarchical" => true,
        "label" => "Commercial Categories",
        "show_ui" => true,
        "show_in_menu" => true,
        "show_in_nav_menus" => true,
        "query_var" => true,
        "rewrite" => array( 'slug' => 'commercial', 'with_front' => false ),
        "show_admin_column" => false,
        "show_in_rest" => true,
        "rest_base" => "commercial-categories",
        "show_in_quick_edit" => false,
    );
    register_taxonomy( "commercial_taxonomies", array( "commercial" ), $args );
}

add_action( 'init', 'cptui_register_my_taxes' );

function cptui_register_my_cpts() {

    /**
     * Post Type: Commercial Products.
     */

    $labels = array(
        "name" => __( "Commercial Products", "" ),
        "singular_name" => __( "Commercial", "" ),
        "add_new" => __( "New Product", "" ),
        "add_new_item" => __( "Add New Product", "" ),
    );

    $args = array(
        "label" => __( "Commercial Products", "" ),
        "labels" => $labels,
        "description" => "",
        "public" => true,
        "publicly_queryable" => true,
        "show_ui" => true,
        "show_in_rest" => true,
        "rest_base" => "",
        "has_archive" => 'commercial',
        "show_in_menu" => true,
        "show_in_nav_menus" => true,
        "exclude_from_search" => false,
        "capability_type" => "post",
        "map_meta_cap" => true,
        "hierarchical" => true,
        "rewrite" => array( "slug" => "commercial/%commercial_taxonomies%", "with_front" => false ),
        "query_var" => true,
        "supports" => array( "title", "editor", "thumbnail", "page-attributes" ),
        "taxonomies" => array( "commercial_taxonomies" ),
    );

    register_post_type( "commercial", $args );
}

add_action( 'init', 'cptui_register_my_cpts' );



function commercial_post_link( $post_link, $id = 0 ){
  $current_post = get_post();
  $current_post_type = $current_post->post_type;

  $terms = wp_get_object_terms( get_the_ID(), $current_post_type.'_taxonomies');
  $term_array = array();

  foreach ($terms as $term) {
    if ($term->parent == 0) {
        array_unshift($term_array, strtolower($term->name));
    }else{
        array_push($term_array, strtolower($term->name));
    }
  }

  $tax_url = join("https://wordpress.stackexchange.com/",$term_array);

  if( count($term_array) > 0 ){
    return str_replace( '%parent_tax%/%child_tax%' , $tax_url , $post_link );
  }
  return $post_link;  
}
add_filter( 'post_type_link', 'commercial_post_link', 1, 3 );

This is how my terms are selected for the post: https://www.dropbox.com/s/ctdvmg6w1fi4stz/Screenshot%202018-08-17%2012.18.54.png?dl=0

This does properly change the url to example.com/commercial/solar/neutral/example-post but I get a 404

The archive pages for /commercial/solar/ and /commercial/solar/neutral/ are working as expected

I also tried adding a custom rewrite rule:

add_filter('rewrite_rules_array', 'mmp_rewrite_rules');
function mmp_rewrite_rules($rules) {
    $newRules  = array();
    $newRules['commercial/(.+)/(.+)/(.+)/?$'] = 'index.php?commercial=$matches[3]';
    $newRules['commercial/(.+)/(.+)/?$']                = 'index.php?commercial_taxonomies=$matches[2]'; 

    return array_merge($newRules, $rules);
}

UPDATE: This is working and I have updated the code in this question to be in working order in case somebody finds this in the future.

Note: my post types are commercial and residential and my taxonomies all follow the same pattern commercial_taxonomies residential_taxonomies using this pattern: post-type-name_taxonomies

Make sure to re-save permalinks after adding all of this or it won’t work.

Here is the working code:

function cptui_register_my_taxes() {

    /**
     * Taxonomy: Commercial Categories.
     */

    $labels = array(
        "name" => __( "Commercial Categories", "" ),
        "singular_name" => __( "Commercial Category", "" ),
    );

    $args = array(
        "label" => __( "Commercial Categories", "" ),
        "labels" => $labels,
        "public" => true,
        "hierarchical" => true,
        "label" => "Commercial Categories",
        "show_ui" => true,
        "show_in_menu" => true,
        "show_in_nav_menus" => true,
        "query_var" => true,
        "rewrite" => array( 'slug' => 'commercial',"hierarchical" => true, 'with_front' => false ),
        "show_admin_column" => false,
        "show_in_rest" => true,
        "rest_base" => "commercial-categories",
        "show_in_quick_edit" => false,
    );
    register_taxonomy( "commercial_taxonomies", array( "commercial" ), $args );
}

add_action( 'init', 'cptui_register_my_taxes' );

function cptui_register_my_cpts() {

    /**
     * Post Type: Commercial Products.
     */

    $labels = array(
        "name" => __( "Commercial Products", "" ),
        "singular_name" => __( "Commercial", "" ),
        "add_new" => __( "New Product", "" ),
        "add_new_item" => __( "Add New Product", "" ),
    );

    $args = array(
        "label" => __( "Commercial Products", "" ),
        "labels" => $labels,
        "description" => "",
        "public" => true,
        "publicly_queryable" => true,
        "show_ui" => true,
        "show_in_rest" => true,
        "rest_base" => "",
        "has_archive" => 'commercial',
        "show_in_menu" => true,
        "show_in_nav_menus" => true,
        "exclude_from_search" => false,
        "capability_type" => "post",
        "map_meta_cap" => true,
        "hierarchical" => true,
        "rewrite" => array( "slug" => "commercial/%commercial_taxonomies%/", "with_front" => false ),
        "query_var" => true,
        "supports" => array( "title", "editor", "thumbnail", "page-attributes" ),
        "taxonomies" => array( "commercial_taxonomies" ),
    );

    register_post_type( "commercial", $args );
}

add_action( 'init', 'cptui_register_my_cpts' );



function custom_post_link( $post_link, $id = 0 ){
  $current_post = get_post();
  $current_post_type = $current_post->post_type;

  $terms = wp_get_object_terms( get_the_ID(), $current_post_type.'_taxonomies');
  $term_array = array();

  // If parent == 0, it means it is a parent and adds it to the beginning of the array, else add it to end of array
  foreach ($terms as $term) {
    if ($term->parent == 0) {
        array_unshift($term_array, strtolower($term->name));
    }else{
        array_push($term_array, strtolower($term->name));
    }
  }

  $tax_url = join("https://wordpress.stackexchange.com/",$term_array);

  if( count($term_array) > 0 ){
    return str_replace( '%'.$current_post_type.'_taxonomies%' , $tax_url , $post_link );
  }
  return $post_link;  
}
add_filter( 'post_type_link', 'custom_post_link', 1, 3 );

add_filter('rewrite_rules_array', 'mmp_rewrite_rules');
function mmp_rewrite_rules($rules) {
    $newRules  = array();
    $newRules['commercial/(.+)/(.+)/(.+)/?$'] = 'index.php?commercial=$matches[3]';
    $newRules['commercial/(.+)/(.+)/?$'] = 'index.php?commercial_taxonomies=$matches[2]';
    $newRules['residential/(.+)/(.+)/(.+)/?$'] = 'index.php?residential=$matches[3]';
    $newRules['residential/(.+)/(.+)/?$'] = 'index.php?residential_taxonomies=$matches[2]'; 

    return array_merge($newRules, $rules);
}

0

Leave a Comment