I’ve run into another wonderful 404 issue. I’m trying to have 2 seperate post types that share the same rewrite slug. I’ve flushed my rewrite rules, and when I test only 1 of the CPT works- the other gets a 404. My rewrite that I wish to use for both is:
'rewrite' => array('slug' => 'team/%teamtype%'),
Anyone know how to handle this?
add_action( 'init', 'create_rider_type' );
function create_rider_type() {
register_post_type('riders',
array(
'description' => 'rider custom post type',
'show_ui' => true,
'menu_position' => 5,
'menu_icon' => get_stylesheet_directory_uri() . '/images/riders.png',
'exclude_from_search' => false,
'labels' => array(
'name' => 'Team Riders',
'singular_name' => 'Rider',
'add_new' => 'Add New rider',
'add_new_item' => 'Add New rider',
'edit' => 'Edit riders',
'edit_item' => 'Edit rider',
'new_item' => 'New rider',
'view' => 'View rider',
'view_item' => 'View rider',
'search_items' => 'Search riders',
'not_found' => 'No riders found',
'not_found_in_trash' => 'No riders found in Trash',
'parent' => 'Parent rider',
),
'hierarchical' => false,
'supports' => array('title','editor','excerpt', 'trackbacks','custom-fields', 'comments','revisions','thumbnail','author','page-attributes'),
'public' => true,
'rewrite' => array('slug' => 'team/%teamtype%'),
'taxonomies' => array('teamtype')
)
);
}
add_action( 'init', 'create_sponsor_type' );
function create_sponsor_type() {
register_post_type('sponsors',
array(
'description' => 'sponsor custom post type',
'show_ui' => true,
'menu_position' => 5,
'menu_icon' => get_stylesheet_directory_uri() . '/images/sponsors.png',
'exclude_from_search' => false,
'labels' => array(
'name' => 'Team sponsors',
'singular_name' => 'sponsor',
'add_new' => 'Add New sponsor',
'add_new_item' => 'Add New sponsor',
'edit' => 'Edit sponsors',
'edit_item' => 'Edit sponsor',
'new_item' => 'New sponsor',
'view' => 'View sponsor',
'view_item' => 'View sponsor',
'search_items' => 'Search sponsors',
'not_found' => 'No sponsors found',
'not_found_in_trash' => 'No sponsors found in Trash',
'parent' => 'Parent sponsor',
),
'hierarchical' => false,
'supports' => array('title','editor','excerpt', 'trackbacks','custom-fields', 'comments','revisions','thumbnail','author','page-attributes'),
'public' => true,
'rewrite' => array('slug' => 'team/%teamtype%'),
'taxonomies' => array('teamtype')
)
);
}
*************Update***********************************
The original CPT rewrite code I posted was simplified so I could get more straight to the point- however maybe it makes more sense if you can see how i’m handling those permalinks with my custom Taxonomy. I’ve updated the code to show.
I really wish to keep them as seperate post types- for organization as well as seperate metaboxes for each. Please check the updated rewrites for the CPT’s, as well as my Taxonomy setup below:
add_action( 'init', 'create_team_taxonomies' );
function create_team_taxonomies() {
register_taxonomy(
'teamtype',
array('riders','sponsors'),
array(
'labels' => array(
'name' => 'Team Types',
'singular_name' => 'Team Type',
'search_items' => 'Search Team Types',
'popular_items' => 'Popular Team Types',
'all_items' => 'All Team Types',
'parent_item' => 'Parent Team Type',
'parent_item_colon' => 'Parent Team Type:',
'edit_item' => 'Edit Team Type',
'update_item' => 'Update Team Type',
'add_new_item' => 'Add New Team Type',
'new_item_name' => 'New Team Type Name'
),
'hierarchical' => true,
'public' => true,
'show_ui' => true,
'query_var' => 'teamtype',
'show_tagcloud' => true,
'rewrite' => array( 'slug' => 'team', 'with_front' => false)
)
);
}
And here is how I setup the rewrite when I select the Taxonomy, and publish the post:
add_filter('post_link', 'teamtypepermalink', 10, 3);
add_filter('post_type_link', 'teamtypepermalink', 10, 3);
function teamtypepermalink($permalink, $post_id, $leavename) {
if (strpos($permalink, '%teamtype%') === FALSE) return $permalink;
// Get post
$post = get_post($post_id);
if (!$post) return $permalink;
// Get taxonomy terms
$terms = wp_get_object_terms($post->ID, 'teamtype');
if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) $taxonomy_slug = $terms[0]->slug;
else $taxonomy_slug = 'not-specified';
return str_replace('%teamtype%', $taxonomy_slug, $permalink);
}
I’ve just done a project where two Custom Post Types needed to share the same slug. The trick is to overwrite the query vars via the
request
filter. Let’s call the post types ‘foo’ and ‘bar’, and they will share slug ‘foo’.The following code is rough and from memory for example only. Salt to taste, do not copy-paste:
I know this question is very old, but when I was looking for a solution to a similar problem, this question came closest to what I was trying to achieve, and since it came up in my search I figured there might not yet be any better solutions available. So I’ll add the solution I came up with below in case it might help someone later on with a similar issue.
I was having a similar problem. I wanted to have a new custom post type that would share the slug with another post type. In my case I had a post type called
country-info
and I wanted to use the same permalink structure as the standardpage
post type.In other words I wanted it to be accessable using
example.com/page-name/
instead ofexample.com/country-info/page-name
.This is how I solved it:
Please note:
In my case the requests I was looking for where all at root level of the domain like
example.com/page-name
, but if your custom post type is within a directory likeexample.com/some-directory/post-name/
, then you will need to change one thing in the code:$pageName = $query->request;
needs to be
$pageName = preg_replace('/my-directory-name//', '', $query->request)
Otherwise get_posts will try to find a post where the slug contains your directory, which will always give you zero results. This preg_replace simply removes your directory name from the string.
Remember to replace
my-directory-name
with the real directory name!This solution is tested and works on WordPress 4.9.7
As far as I know, you can’t do that. Every slug is converted to a query_vars item that queries a specific object type (taxonomy or post type). If you analice your WP_Query, you’ll see that is querying the first post type.
Maybe a WP Ninja here can enlighten us with this, but I’m almost sure that you can’t do it. Or at least, you shouldn’t.
As CPTs (and posts / pages, for that matter) are constructed, that’s not possible. The slug is reserved for the specific type, with the understanding / assumption that 2 CPTs = 2 different types of content.
based on your code, it almost seems like each of the items you have in the CPT would be better be served as a custom taxonomy, with both being attached to a single CPT (I’m guessing some sort of event?)
Your rewrite rules will overwrite each other, and WordPress will query for only one of the post types. I think it is the latest one that is registered that “wins”, so
/testslug/bmw/
will always query for a post with slugbmw
and post typesponsors
. If you go to/testslug/some-name/
andsome-name
is a rider, it will still query for post typesponsors
and post slugsome-name
. It will find no post, and thus give you a 404. This happens in the “default” query that WordPress will do for you, before it loads the template page, so you can’t solve this in yoursingle-sponsors.php
template file for example (you could in404.php
, but then it gets ugly).The cleanest solution is to replace part of the logic that does this URL parsing, and make it accept an “ambiguous” URL. Test whether it is a rider or a sponsor, and change the parameters so WordPress will continue with either a rider or a sponsor. Mike once provided a way to do this with pages and taxonomies, it should be possible to extend this to work with posts only.