Custom single template for a specific category

What is the best way (performance & code structure) to create a custom template for a WordPress Post, which belong to a specific category? I realized that you can’t just create single-catname.php.

So far i tried two ways to change the template. But which one (or another one) is the best?


Any idea how to include all the sub/parent and so on categories to? I realized right now it only shows the main category…

1. Added to functions.php

function get_custom_cat_template($single_template) {
   global $post;
   if ( in_category( 'movies' )) {
      $single_template = dirname( __FILE__ ) . '/single-movies.php';
   return $single_template;
add_filter( "single_template", "get_custom_cat_template" ) ;

2. Put the following Code in to single.php (instead of all other code) and create a single-template.php (with the code from the single.php) & a custom single-movies.php

if(has_term('movies', 'category', $post)) {      
   get_template_part('single-movies', 'movies');
} else {
   // use default template file single-template.php


From my comment to the OP

My opinion, use what you are comfortable with. If there are any performance difference it will be minute/irrelevant. My preference, use the filter

To come to your real concern/question, in my opinion, the best approach will be to use the parent category ID and work from there. It will be the least resource intensive to work from here. Reverse engineering can become quite an unnecessary waste of resources.

Make use of get_categories to get the child categories from the given category. You can make use of either one of two parameters, either parent or child_of

parent (integer)

Display only categories that are direct descendants (i.e. children only) of the category identified by its ID. This does NOT work like the ‘child_of’ parameter. There is no default for this parameter. [In 2.8.4]

child_of (integer)

Display all categories that are descendants (i.e. children & grandchildren) of the category identified by its ID. There is no default for this parameter. If the parameter is used, the hide_empty parameter is set to false.

Once you have these, use wp_list_pluck to get the catID, name or slug fields from the returned array of categories. This array will be used to check if a post belongs to one of these categories. You can either use has_category or in_category

This is how you can extend your code to make sure that posts belonging to either the parent category or its descendants uses the given template

add_filter( 'single_template', function ( $single_template ) {

    $parent="21"; //Change to your category ID
    $categories = get_categories( 'child_of=" . $parent );
    $cat_names  = wp_list_pluck( $categories, "name' );

    if ( has_category( 'movies' ) || has_category( $cat_names ) ) {
        $single_template = dirname( __FILE__ ) . '/single-movies.php';
    return $single_template;
}, PHP_INT_MAX, 2 );

Leave a Comment