I’ve got these custom post types (CPT) and meta boxes:
- Movies (CPT)
- Genre (Meta box)
- Genres (CPT)
If one movie is called Die hard then I want the permalink to be:
/genres/action/die-hard
This is easily fixed by setting the movie-CPT to ‘rewrite’ => false and use this code instead:
add_action('init', 'rb_add_rewrite_rules');
add_filter('post_type_link', 'rb_create_permalinks', 10, 3);
function rb_add_rewrite_rules() {
global $wp_rewrite;
$wp_rewrite->add_rewrite_tag('%movies%', '([^/]+)', 'movies=');
$wp_rewrite->add_rewrite_tag('%genre%', '([^/]+)', 'genre=');
$wp_rewrite->add_permastruct('movies', '/genres/%genre%/%movies%', false);
}
function rb_create_permalinks($permalink, $post, $leavename) {
$no_data = 'no-data';
$post_id = $post->ID;
if($post->post_type != 'movies' || empty($permalink) || in_array($post->post_status, array('draft', 'pending', 'auto-draft')))
return $permalink;
$event_id = get_post_meta($post_id, 'genre', true);
$var1 = basename(get_permalink($event_id));
$var1 = sanitize_title($var1);
if(!$var1)
$var1 = $no_data;
$permalink = str_replace('%genre%', $var1, $permalink);
return $permalink;
}
Ok, here’s the problem. Both the Die Hard permalink and the archive-genres.php (displaying all the genres) is looking good, but the single-genres.php isn’t found – instead, going to /genres/action will display the index.php code.
I guess the problem is that my rewrites collide, maybe it’s not possible to do this:
‘movies’ CPT permalink
/custom base name/custom field meta box value)/'movies' CPT post name
‘genres’ CPT permalink
/custom post type name (same value as the custom base name above!!)/'genres' CPT post name
How can I make WordPress use single-genres.php for /genres/action etc?
It sounds like you’re very close here and your only remaining issue is that your permalinks for genres and movies collide.
The issue here is using the
add_permastruct
. When it creates the rules for movies, they look something like this:The way request processing works in WordPress, you can’t set multiple post types in the same URL — WordPress stops after the first one. That is, they can be in the pretty URL, but not in the “ugly” one that generates the request and query. Any rewrite rules with
movies=
cannot containgenre=
. Below is the full, exhausting overhaul ofrb_add_rewrite_rules
. You can pull out any rules you may not need like the attachment urls, feed urls, etc. As always when making rewrite changes, be sure to flush your permalinks by going to Settings->Permalinks and clicking “Save Changes”. Also, make sure'rewrite' => false
is set on both custom post types.I think you’re taking the wrong approach in terms of data structure. You should create a custom taxonomy called Genres, and bind your movies CPT to the Genres custom taxonomy, and then select which Genres the movie belongs to.
To address questions about your existing code. single-XXX.php template is used to display content from the CPT called XXX. So in order to display movies, you should use single-movies.php. And address content specifically for a particular post_meta, you can do the following: