Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

For some reason I can not create multiple CPT with the same URL structure, for instance I can not get the following to work:

/cpt1/overview
/cpt1/events

/cpt2/overview
/cpt2/events

What ends up happening is the following:

/cpt1/overview
/cpt1/events

/cpt2/overview-2
/cpt2/events-2

I tried the following on a clean install of wp to make sure nothing was messing it up:

add_action( 'init', function() 
{
    register_post_type( 'cpt1', array(
        'labels' => array(
            'name'                  => __('CPT1'),
            'singular_name'         => _x('Page', 'singular name'),
            'add_new'               => _x('Add New', 'page'),
            'all_items'             => __('All Pages'),
            'add_new_item'          => __('Add New Page'),
            'edit_item'             => __('Edit Page'),
            'new_item'              => __('New Page'),
            'view_item'             => __('View Page'),
            'search_items'          => _x('Search Pages', 'plural'),
            'not_found'             => _x('No pages found', 'plural'),
            'not_found_in_trash'    => _x('No pages found in Trash', 'plural'), 
            'parent_item_colon'     => '',
        ),
        'public' => true,
        'has_archive' => true,
        'rewrite' => array( 'slug' => 'cpt1', 'with_front' => false ),
        'show_in_nav_menus' => false,
        'hierarchical' => true,
        'supports' => array( 'author', 'title', 'editor', 'custom-fields', 'page-attributes', 'revisions' ),
    ));
} );

add_action( 'init', function() 
{
    register_post_type( 'cpt2', array(
        'labels' => array(
            'name'                  => __('CPT2'),
            'singular_name'         => _x('Page', 'singular name'),
            'add_new'               => _x('Add New', 'page'),
            'all_items'             => __('All Pages'),
            'add_new_item'          => __('Add New Page'),
            'edit_item'             => __('Edit Page'),
            'new_item'              => __('New Page'),
            'view_item'             => __('View Page'),
            'search_items'          => _x('Search Pages', 'plural'),
            'not_found'             => _x('No pages found', 'plural'),
            'not_found_in_trash'    => _x('No pages found in Trash', 'plural'), 
            'parent_item_colon'     => '',
        ),
        'public' => true,
        'has_archive' => true,
        'rewrite' => array( 'slug' => 'cpt2', 'with_front' => false ),
        'show_in_nav_menus' => false,
        'hierarchical' => true,
        'supports' => array( 'author', 'title', 'editor', 'custom-fields', 'page-attributes', 'revisions' ),
    ));
} );

Is what I am after possible? and how?

Further Discoveries

1

As I am working with this further .. it seems like wordpress will redirect the following (with out me doing any extra config) ...

/cpt2/overview/
/cpt2/events/

to

/cpt2/overview-2/
/cpt2/events-2/

2

I found the following wp function wp_unique_post_slug (with an available filter) which checks slugs for pages/posts returning a unique slug if it finds a duplicate (appending -2, -3, etc) .. if you look at the function itself, it does do a post_type check but only if the post_type is set as non hierarchical .. otherwise it finds all hierarchical post_types and checks for uniqueness from all (e.g. post, page, book, event .. as an example).

share|improve this question
add comment

1 Answer

This is my solution to my problem above, I would love more feedback and/or a better solution ... the below uses code from wp_unique_post_slug which checks for slug uniqueness only within the custom post type and within the hierarchy.

Note: this works because cpt1 and cpt2 use their own permalink prefixes ...

add_filter( 'wp_unique_post_slug', function( $slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug ) 
{
    if ( in_array( $post_type, array( 'cpt1', 'cpt2' ) ) )
    {
        // start with a base slug w/o any suffixes
        $slug = preg_replace( '/(-\d+)$/', '', $slug );

        global $wpdb, $wp_rewrite;

        $feeds = $wp_rewrite->feeds;
        if ( ! is_array( $feeds ) )
            $feeds = array();

        $check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type = %s AND ID != %d AND post_parent = %d LIMIT 1";

        $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_type, $post_ID, $post_parent ) );

        if ( $post_name_check || in_array( $slug, $feeds ) || preg_match( "@^($wp_rewrite->pagination_base)?\d+$@", $slug )  || apply_filters( 'wp_unique_post_slug_is_bad_hierarchical_slug', false, $slug, $post_type, $post_parent ) ) {
            $suffix = 2;
            do {
                $alt_post_name = substr( $slug, 0, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
                $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $post_type, $post_ID, $post_parent ) );
                $suffix++;
            } while ( $post_name_check );
            $slug = $alt_post_name;
        }
    }

    return $slug;
}, 10, 6 );
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.