12

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 Answer 1

16

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.

12
  • So, this works, but it turns out the template_redirect and single_template work too. The real problem I determined was that I have a custom admin column sorting function that hooks into the 'request' filter and I wasn't limiting the modification of the $vars variable to only when post type was of a certain type. But, I'm glad to know about the template_include hook. Still not sure what the difference is between template_redirect, template_include and single_template though.
    – anderly
    Mar 2, 2012 at 17:24
  • @anderly I updated my answer. Hope this helps. Mar 2, 2012 at 17:36
  • 1
    single_template works the same way except it's called conditionally. This helps to isolate path changes instead of using a hammer filter on the whole site. Mar 2, 2012 at 17:42
  • 1
    very cool... i didn't know about template_include Mar 2, 2012 at 20:39
  • 1
    FYI, single_template has been removed as of 3.4. Use {posttype}_template instead. Jan 2, 2013 at 18:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.