Cynthia
Cynthia

Reputation: 5403

How to have WordPress use a custom single.php template if the post is in a specific category OR its children?

I have a standard single.php that will be used by most posts on this website I am working on, but for a specific category and its subcategories, I want to use a custom single.php. How do I do that? I know the logic behind what I want, I'm just not sure how to write it.

Here is the code I am using but it isn't working:

<?php

$post = $wp_query->post;

if ( in_category('2,6,7,8') ) {

include(TEMPLATEPATH . '/single-blog.php'); } 

else {

include(TEMPLATEPATH . '/single-default.php');

}

?>

Cat IDs 6, 7 and 8 are subcats of Cat ID 2.

Any help would be most appreciated!

Thanks,

Cynthia

Upvotes: 0

Views: 2593

Answers (3)

helgatheviking
helgatheviking

Reputation: 26319

I think you need to filter template_include or even better single_template. I'm leaving the has_category() conditional as hard-coded, but you could do something to get the top-level category and always test that instead.

EDIT now using post_is_in_descendant_category() from a codex example. Note, this isn't a built-in WordPress function so you need to include it in your plugin/theme.

EDIT #2 Use locate_template() to ensure that the file is really there.

function get_custom_category_template($single_template) {

     if ( in_category( 'blog' ) || post_is_in_descendant_category( 2 ) ) {
          $new_template = locate_template( array( 'single-blog.php' ) );
          if ( '' != $new_template ) {
            $single_template = $new_template ;
          }
     }
     return $single_template;
}
add_filter( 'single_template', 'get_custom_category_template' );

/* Checks if a category is a descendant of another category */

if ( ! function_exists( 'post_is_in_descendant_category' ) ) {
    function post_is_in_descendant_category( $cats, $_post = null ) {
        foreach ( (array) $cats as $cat ) {
            // get_term_children() accepts integer ID only
            $descendants = get_term_children( (int) $cat, 'category' );
            if ( $descendants && in_category( $descendants, $_post ) )
                return true;
        }
        return false;
    }
}

Upvotes: 2

Cynthia
Cynthia

Reputation: 5403

I figured it out! helgatheviking's suggestion about the top-level category got me thinking about ancestor and descendant categories. From there I discovered the post_is_in_descendant_category function.

After putting the following function in my functions.php:

/* Checks if a category is a descendant of another category */

if ( ! function_exists( 'post_is_in_descendant_category' ) ) {
    function post_is_in_descendant_category( $cats, $_post = null ) {
        foreach ( (array) $cats as $cat ) {
            // get_term_children() accepts integer ID only
            $descendants = get_term_children( (int) $cat, 'category' );
            if ( $descendants && in_category( $descendants, $_post ) )
                return true;
        }
        return false;
    }
}

I figured out how to modify my original category query and template assignment like this:

<?php

$post = $wp_query->post;

if ( in_category( 'blog' ) || post_is_in_descendant_category( 2 ) ) {

include(TEMPLATEPATH . '/single-blog.php'); } 

else {

include(TEMPLATEPATH . '/single-default.php');

}

?>

Thanks to everyone who tried to assist. I appreciate it a lot!

Upvotes: 1

teeyo
teeyo

Reputation: 3755

Updated

You can go for single-[post-type].php.

Read more about The Template File Hierarchy

Upvotes: 1

Related Questions