6
votes

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.

1
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

1 Answers

4
votes

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