Showing posts with different templates, the “single_template” filter

Habitualy, the WordPress template hierarchy for posts, uses a simple descendant decision tree for choosing which single_template.php file is going to be used for showing a single post. This decision tree is quite usefull so that, simply creating a .php file called like single, single-posttype, etc., it’s possible to control very accurately which template will be used for showing data.

Normal Decision Tree for Single Elements

However, in contrast of pages that each one can have its own template, ie, they have a very flexible decision rules, choosing the templates for posts is ruled by criterias more restrictive based in sets of elements, ie, “is_an_attachment”, then “is_a_post_type”, then “is a post” and finally “is_a_singular_element” so that, it’s not even possible to choose by ID for example, like with pages, or to decide a specífic template…

Spite of this restriction, there is a solution based on using a filter called single_template, strictly speaking {$type]_template, that is fired at the end of the normal seleccion template process and that’s possible to use for choosing a different template for some “types” of elements. In our case, we are thinking in filtering all elements that belong to type single, under our own rules. See this next example:

<?php
function modifying_single_template ( $template ) {

     global $post;

     $terms_in_tax1 = wp_get_object_terms($post->ID, 'your_special_tax_1', array ( 'fields' => 'names' ) );
     $terms_in_tax2 = wp_get_object_terms($post->ID, 'your_special_tax_2', array ( 'fields' => 'names' ) );

     // Here your special rules
     if (
           ( $post->post_type == 'my_special_post_type' )      &&    // your rule number 1
           ( $post->post_author == 'my_special_author' )       &&    // your rule number 2
           // more rules based on the current post
           ( $post->post_date >= 'my_special_formatted_date' ) &&    // your rule number n  
           
           // for example, here rules based on taxs
           ( 
              ( in_array ( 'your_check_tax_name1', $terms_in_tax1 ) ) ||   // your rule 1 based on taxs
              ( in_array ( 'your_check_tax_name2', $terms_in_tax2 ) ) ||   // your rule 2 based on taxs
              // more rules based on taxs
           )
        )
     {
          // here we rewrite the $template name var
          $template = dirname( __FILE__ ) . '/templates/your-special-template.php';
     }

     return $template;

}
add_filter( 'single_template', 'modifying_single_template' );
?>

In this example, we use the filter single_template (For further information, see the official documentation of filter single_template) for checking if the current post belongs to ‘my_special_post_type’, then if it is written by ‘my_special_author’, etc. and too, if the current post belongs to any of the terms ‘your_check_tax_namen‘ in two specific taxonomies, In that case, if all rules are TRUE, we return a special template name for showing the current post.

Well, this is only and example but it shows how can you modify the template choosen by default for the elements that habitually should use the single.php template.

Be carefull with this filter because it depends on the name of the standard template (single, category, etc.) and in addition, it is fired by WordPress before the common filter template_include, the most general WordPress filter for reassigning templates so that, all changes that you make in single_template filter could be rewritten by the next filter.

A final thought about this, think carefully if you do really need to use this filter; there are a lot of strategies before creating specific templates for posts and in consequence to modify the normal flow of WordPress: attachments, mime_types, post_formats, post_types… Are you sure that you need to use this filter?

Have a nice WordPressing!

Leave a Comment

   Mandatory field
You can use these HTML tags inside the commment.
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>