This was a bit tricky to solve your problem.
the template_include
filter executed after the main query processed the current request. If you can filter the current request (query_vars) and update it accordingly then WordPress will display any post/page you wanted to… Simply filter the query_vars
with the request
filter. Check the following snippet. But doing this might have a bad effect on SEO.
add_filter( 'request', function( $query_vars ) {
if( is_admin() ) return $query_vars;
$_post = null;
// find the queried post
if( isset( $query_vars['post_type'], $query_vars['your-post-type'] ) && $query_vars['post_type'] == 'your-post-type' ) {
// $query_vars['your-post-type'] will contains the post slug
$_post = get_page_by_path( $query_vars['your-post-type'], OBJECT, $query_vars['post_type'] );
} else if( isset( $query_vars['p'] ) ) {
$_post = get_post( $query_vars['p'] );
if( $_post != 'your-post-type' ) $_post = null;
}
if( $_post ) { // post found
// get the redirect to page id
$custom_page_id = get_post_meta( $_post->ID, 'custom_page_id', true );
$custom_page = get_post( $custom_page_id );
if( $custom_page ) { // valid page/post found.
// set the query vars to display the page/post
$query_vars[$custom_page->post_type] = $custom_page->post_name;
$query_vars['name'] = $custom_page->post_name;
$query_vars['post_type'] = $custom_page->post_type;
}
}
return $query_vars;
}, 10 );