6

I have multiple custom post types with custom taxonomies. I'm having a slug clash despite of having different parents.

Here is my URL structure: /work/%client_name%/%project_name%

I have a client (client1) and project (some-cool-project-name) that generates this slug: "/work/client1/some-cool-project-name".

When I create a new post under a different parent (client) and give the same name (and slug) to the post, wordpress appends -2 to the slug: "/work/client2/some-cool-project-name-2"

Custom post type as:

// Custom taxonomies.
function custom_taxonomies() {
    $args = array(
        'label' => __( 'Work', '' ),
        'labels' => array(
            'name' => __( 'Work', '' ),
            'singular_name' => __( 'Work', '' ),
        ),
        'description' => '',
        'public' => true,
        'publicly_queryable' => true,
        'show_ui' => true,
        'show_in_rest' => false,
        'rest_base' => '',
        'has_archive' => true,
        'show_in_menu' => true,
        'exclude_from_search' => false,
        'capability_type' => 'post',
        'map_meta_cap' => true,
        'hierarchical' => true,
        'rewrite' => array( 'slug' => 'work/%client_name%', 'with_front' => true ),
        'query_var' => true,
        'menu_icon' => 'dashicons-hammer',
        'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt', 'page-attributes' ),
        'taxonomies' => array( 'client_name' ),
    );
    register_post_type( 'work', $args );

    $args = array(
        'label' => __( 'Clients', '' ),
        'labels' => array(
            'name' => __( 'Clients', '' ),
            'singular_name' => __( 'Client', '' ),
        ),
        'public' => true,
        'hierarchical' => false,
        'label' => 'Clients',
        'show_ui' => true,
        'show_in_menu' => true,
        'show_in_nav_menus' => true,
        'query_var' => true,
        'rewrite' => array( 'slug' => 'work/client_name', 'with_front' => false, ),
        'show_admin_column' => false,
        'show_in_rest' => false,
        'rest_base' => '',
        'show_in_quick_edit' => false,
    );
    register_taxonomy( 'client_name', array( 'work' ), $args );
}
add_action( 'init', 'custom_taxonomies' );

And my permalink rewrite:

// Replace URL with proper taxonomy structure.
function permalink_rewrites( $link, $post ) {
    if ( $post->post_status !== 'publish' || $post->post_type != 'work' ) {
        return $link;
    }

    if ( $post->post_type == 'work' ) {
        $type = '%client_name%/';
        $filters = get_the_terms( $post->ID, 'client_name' );
        $slug = $filters[0]->slug . '/';
    }

    if ( isset( $slug ) ) {
        $link = str_replace( $type, $slug, $link );
    }

    return $link;
}
add_filter( 'post_type_link', 'permalink_rewrites', 10, 2 );

Any suggestions on what I can do this fix this?

Thanks.

ialphan
  • 1,231
  • 1
  • 17
  • 29
  • 3
    In wordpress any post, taxonomy, custom post type , pages etc all must have unique slugs, wordpress never allow to create the page and post with same slug. – dipmala Jun 14 '18 at 07:09

1 Answers1

4

Unfortunately WordPress isn't really designed this way. Part of why this doesn't work for 2 Posts/CPTs even in separate categories, is what happens when one is in both categories? You'd have to start getting some nasty rewrite rules and the redirect_canonical() function involved - at which point you're just asking for 404 errors out the wazoo.

Luckily, instead of relying on taxonomies and CPTs with the same slug, there is something you could do. You could instead drop the taxonomy part of it and use the hierarchical format of your custom post type.

Part of why this works is because you can't assign multiple parents to one post/CPT, so there are no permastruct clashes.

Create a new "Work" called Client 1 and a second called Client 2.

Now, with those "parent works" created, you can create a third "Work" called Cool Project and set the Parent to Client 1, and then create fourth called Cool Project as well and set the parent to Client 2.

This will give you the following permalink structure:

https://example.com/work/client-1/cool-project
https://example.com/work/client-2/cool-project

You can see this in action right now here:

These are set up exactly the way I mentioned:

The downside of this is, is that if you use the /work/client-name page to display anything, you'll now have to set up a Post Type Template (Available since WP 4.7.0) to achieve the functionality that you have with the archive template instead.

However it prevents the need for redirects and rewrite rules.

Here's a screenshot of the permalink structure: Here's a screenshot of the permalink structure

Here's a screenshot of the CPT Overview admin page: Here's a screenshot of the CPT Overview admin page

Xhynk
  • 12,250
  • 8
  • 29
  • 61
  • Thanks for your response @Xhynk. Could you elaborate on "drop the taxonomy part of it and use the hierarchical format of your custom post type"? I can see how this could work. But it seems to be too ugly. :( Is this the only way? – ialphan Jul 03 '18 at 15:50
  • Sure - right now you're relying on a taxonomy (`client_name`) for the permalink. So you have `example.com/client-1/project-1`. In order to have "Cool Project" with the slug "cool-project" on both Client 1 & 2, you _can not_ use the taxonomy like that in the permalink structure. I wouldn't say it's _ugly_, as `example.com/parent/child` is an extremely common naming convention, even if it's not your desired `example.com/taxonomy/post`. You in order to have the same post name and slug, you can't rely on the taxonomy for the permalink, and instead need to use a parent post. – Xhynk Jul 03 '18 at 19:19
  • The "ugliest" part is that you'll need to create "Client 1" and "Client 2" as "projects", but I think it still has some semblance of order. Unfortunately WordPress isn't really designed around having the same post slug in more than one place – Xhynk Jul 03 '18 at 19:20
  • Thanks for your explanation. @Xhynk – ialphan Jul 04 '18 at 13:18