I tackled subordinate post types with a similar vein but was not as strict on the canonical url aspect; however, I ran into a similar situation with deeplinking custom WooCommerce product type links.
I leveraged the template_redirect
hook to push a 404 if it didn’t match the route and the post_type_link
to ensure the meta tag for canonical link and all the_permalink()
and get_permalink()
references matched the intended link.
A snippit of the way I would recommend handling this:
add_action( 'template_redirect', 'wp20140320_template_redirect' );
public function wp20140320_template_redirect(){
global $wp_query, $post;
// the character post type has the book id set as meta?
// or could set as post_parent if you don't have characters heirarchical
$book_id = get_post_meta( $post->ID, '_book_id', true );
// compare_parent_slug_to_id to check required $book_id against set parent book slug
if( $post->post_type == 'character' && ! compare_parent_slug_to_id( $book_id ) ){
// set is_404 since post type is character and parent slug does not match set
$wp_query->is_404 = true;
status_header(404);
include get_404_template();
exit; // maybe a better way to gracefully exit?
}
}
Modified from source