Custom Post Types and template_redirect

I have two custom post types (e.g. post_type_1 and post_type_2) that I would like to redirect to independent templates (single-post_type_1.php and single-post_type_2.php) to handle their display. I don’t want to put the display templates in the theme folder as I want them self-contained in their respective plugin folders.

How can I have each of them register a template_redirect hook without affecting the other? Or should I be using a different technique?

Currently, I’m doing this in Plugin 1:

add_action( 'template_redirect', 'template_redirect_1' );
function template_redirect_1() {
    global $wp_query;
    global $wp;

    if ( $wp_query->query_vars['post_type'] === 'post_type_1' ) {

        if ( have_posts() )
        {
            include( PATH_TO_PLUGIN_1 . '/views/single-post_type_1.php' );
            die();
        }
        else
        {
            $wp_query->is_404 = true;
        }

    }
}

And this in Plugin 2:

add_action( 'template_redirect', 'template_redirect_2' );
function template_redirect_2() {
    global $wp_query;
    global $wp;

    if ( $wp_query->query_vars['post_type'] === 'post_type_2' ) {

        if ( have_posts() )
        {
            include( PATH_TO_PLUGIN_2 . '/views/single-post_type_2.php' );
            die();
        }
        else
        {
            $wp_query->is_404 = true;
        }

    }
}

Once I register plugin 2’s template_redirect hook, plugin 1’s no longer works.

Am I missing something?

What is the best way to do this?

1
1

You should be using the template_include filter for this:

add_filter('template_include', 'wpse_44239_template_include', 1, 1);
function wpse_44239_template_include($template){
    global $wp_query;
    //Do your processing here and define $template as the full path to your alt template.
    return $template;
}

template_redirect is the action called directly before headers are sent for the output of the rendered template. It’s a convenient hook to do 404 redirects, etc… but shouldn’t be used for including other templates paths as WordPress does this innately with the ‘template_include’ filter.

template_include and single_template hooks deal ONLY with the path of the template used for rendering the content. This is the proper place to adjust a template path.

Update from comment by @ChipBennett:

single_template has been removed as of 3.4. Use {posttype}_template instead.

Leave a Comment