You should probably not use template_redirect because it can blow away everything else that WordPress does with the Template Hierarchy – its called right at the beginning of template-loader.php. Also, it mean you need to include the template yourself in some way or another, which is kind of annoying.
Looks like your targeting single posts. I take it that /category/ in your example permalinks actually refers to /category-name/, not the /category/ base that is required for category indexes.
Since your targeting single posts, its best to filter ‘single_template’. Optionally you can check for post type, since single templates can be pages or posts, and you may not want that.
You have a second problem though, and its actually more complicated. The /details bit at the end of your url won’t be captured. The rewrite rules are going to be confused by it and throw a 404 at you. So to capture that your going to need to add something to the rewrite rules. Try this, I tested this a little and it seems to work.
function detail_rewrite_rule( $rules ) {
$newrules = array();
$newrules['(.+?)/([^/]+)(/[0-9]+)?/detail/?$'] = 'index.php?category_name=$matches[1]&name=$matches[2]&page=$matches[3]&detail=1';
return $newrules + $rules;
}
add_filter( 'rewrite_rules_array','detail_rewrite_rules' );
function detail_flush_rules(){
$rules = get_option( 'rewrite_rules' );
if ( ! isset( $rules['(.+?)/([^/]+)(/[0-9]+)?/detail/?$'] ) ) {
global $wp_rewrite;
$wp_rewrite->flush_rules();
}
}
add_action( 'init','detail_flush_rules' );
That should extend your permalink structure to allow you to add ‘detail’ to the query string and give it a value of ‘1’. Which we can then check for when filtering the template.
function filter_single_template($template){
$object = get_queried_object();
$templates = array();
/* If detail is in the query string, create a list of templates to use */
if($_GET['detail']) {
$templates[] = "detail-single.php";
$templates[] = "detail-single-{$object->post_type}.php";
}
/* If one of our custom detail templates exists, return it.
* Otherwise return the original template
*/
return (!empty(locate_template($templates))) ? locate_template($templates) : $template;
}
add_filter('page_template', 'filter_single_template');
What were doing here is checking to see if $_GET[‘detail’] is true, and if it is, were creating a hierarchical list of templates to use – if they exist. The locate_template function will look through the list from top to bottom and return the path to the first one it finds. Later, we check to see if locate_template() found anything at all, if not, we keep the original template which might be single-{post_type}.php, single.php, or index.php.
By doing it this way, you not only preserve the original Template Hierarchy, you are actually extending it.