Custom Post type and Taxonomy using same slug with rewrite
Asked Answered
E

1

7

This is my first attempt at working with WordPress rewrite rules so please bear with me. The issue is that all the items I add to my portfolio have multiple categories. I would like to remove the category from the url when displaying the portfolio posts.

site.com/portfolio -> Works

site.com/portfolio/category/ -> Works

site.com/portfolio/category/post-added-to-portfolio/ -> Works but I don't want it to

site.com/portfolio/post-added-to-portfolio/ -> Does not Work but it should

/* Post Type: Portfolio */
$labels = array(
    "name" => __( "Portfolio", "" ),
    "singular_name" => __( "Portfolio", "" ),
);
$args = array(
    "label" => __( "Portfolio", "" ),
    "labels" => $labels,
    "description" => "",
    "public" => true,
    "publicly_queryable" => true,
    "show_ui" => true,
    "show_in_rest" => false,
    "rest_base" => "",
    "has_archive" => "portfolio",
    "show_in_menu" => true,
    "exclude_from_search" => false,
    "capability_type" => "post",
    "map_meta_cap" => true,
    "hierarchical" => true,
    "rewrite" => array( "slug" => "portfolio", "with_front" => true ),
    "query_var" => true,
    "supports" => array( "title", "editor" ),
    "taxonomies" => array( "services" ),
);
register_post_type( "portfolio", $args );   

/* Taxonomy: Services */
$labels = array(
    "name" => __( "Services", "" ),
    "singular_name" => __( "Service", "" ),
);
$args = array(
    "label" => __( "Services", "" ),
    "labels" => $labels,
    "public" => true,
    "hierarchical" => true,
    "label" => "Services",
    "show_ui" => true,
    "show_in_menu" => true,
    "show_in_nav_menus" => true,
    "query_var" => true,
    "rewrite" => array( 'slug' => 'portfolio', 'with_front' => true, ),
    "show_admin_column" => false,
    "show_in_rest" => false,
    "rest_base" => "",
    "show_in_quick_edit" => false,
);
register_taxonomy( "services", array( "portfolio" ), $args );

// handle redirects for taxonomy
add_action('generate_rewrite_rules', 'generate_taxonomy_rewrite_rules');
function generate_taxonomy_rewrite_rules( $wp_rewrite ) {
  $rules = array();
  $post_types = get_post_types( array( 'name' => 'portfolio', 'public' => true, '_builtin' => false ), 'objects' );
  $taxonomies = get_taxonomies( array( 'name' => 'services', 'public' => true, '_builtin' => false ), 'objects' );
  foreach ( $post_types as $post_type ) {
    $post_type_name = $post_type->name;
    $post_type_slug = $post_type->rewrite['slug'];
    foreach ( $taxonomies as $taxonomy ) {
      if ( $taxonomy->object_type[0] == $post_type_name ) {
        $terms = get_categories( array( 'type' => $post_type_name, 'taxonomy' => $taxonomy->name, 'hide_empty' => 0 ) );
        foreach ( $terms as $term ) {
          $rules[$post_type_slug . '/' . $term->slug . '/?$'] = 'index.php?' . $term->taxonomy . '=' . $term->slug;
          $rules[$post_type_slug . '/' . $term->slug . '/page/?([0-9]{1,})/?$'] = 'index.php?' . $term->taxonomy . '=' . $term->slug . '&paged=' . $wp_rewrite->preg_index( 1 );
        }
      }
    }
  }
  $wp_rewrite->rules = $rules + $wp_rewrite->rules;
}
Every answered 13/4, 2018 at 0:39 Comment(8)
I have solution for Your problem. I have already solved it in one of my blog post here: [Easily remove ‘/Category’ base from all WordPress post’s permalink][1] [1]: siradhana.com/blog/…Plemmons
Just wondering, how come when registering the taxonomy, in args, you have the same slug 'portfolio' as when registering the CPT?Irishirishism
It removes unnecessary url structure.Every
If you set the Permalink structure to http://example.com/%postname%/, you'd get the "portfolio" URL structure that you wanted to have; i.e. example.com/portfolio/sample-portfolio, where sample-portfolio is the "portfolio" slug. Is that not happening, or are you using a different Permalink structure?Instep
I have tried your code into my local, site.com/portfolio/post-added-to-portfolio/ is working for me. and site.com/portfolio/category/post-added-to-portfolio/ do not working for me. what would be your permalink structure?Berneicebernelle
Your comment goes directly against what im trying to do. I want site.com/portfolio/post-added-to-portfolio/ not site.com/portfolio/category/post-added-to-portfolio/Every
Using the same slug twice is not a good idea and will almost certainly cause problems and unexpected behavior. Seems like the answer to this will just be proper use of the permalink settings in WordPress. What is your permalink structure currently set to?Billie
I agree with @Myles. It is a very bad idea to have two identical slugs and it is very likely that you will run into problems with your permalink structure.Forbis
E
-2

After working on this for a week I finally solved the issue. I kept the post types exactly as they were. I replaced the generate_rewrite_rules function with the following.

add_filter('request', 'setTermRequest', 1, 1 );
function setTermRequest($query){
    $tax_name = 'services';
    if( $query['attachment'] ) :
        $include_children = true;
        $name = $query['attachment'];
    else:
        $include_children = false;
        $name = $query['name'];
    endif;
    $term = get_term_by('slug', $name, $tax_name); // get the current term to make sure it exists
    if (isset($name) && $term && !is_wp_error($term)): // check it here
        if( $include_children ) {
            unset($query['attachment']);
            $parent = $term->parent;
            while( $parent ) {
                $parent_term = get_term( $parent, $tax_name);
                $name = $parent_term->slug . '/' . $name;
                $parent = $parent_term->parent;
            }
        } else { unset($query['name']); }
        switch( $tax_name ):
            case 'category':{
                $query['category_name'] = $name; // for categories
                break;
            }
            case 'post_tag':{
                $query['tag'] = $name; // for post tags
                break;
            }
            default:{
                $query[$tax_name] = $name; // for another taxonomies
                break;
            }
        endswitch;
    endif;
    return $query;
}
add_filter( 'term_link', 'writeTermPerm', 10, 3 );
function writeTermPerm( $url, $term, $taxonomy ){
    $taxonomy_name = 'services';
    $taxonomy_slug = 'services';
    if ( strpos($url, $taxonomy_slug) === FALSE || $taxonomy != $taxonomy_name ) return $url;
    $url = str_replace('/'.$taxonomy_slug, '/portfolio', $url);
    return $url;
}

After that fixed the url structure I added the following code to my taxonomy-services.php document in order to control the entire system in one file.

locate_template( 'archive-portfolio.php', true );
Every answered 20/4, 2018 at 18:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.