15

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?

EDIT:

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

<?php        
if(has_term('movies', 'category', $post)) {      
   get_template_part('single-movies', 'movies');
} else {
   // use default template file single-template.php
   get_template_part('single-template');
}
?>
3
  • My opinion, use what you are comfortable with. If there are any performance difference it will be minute/irrelevant. My preference, use the filter Commented Nov 29, 2014 at 10:40
  • Thx for the quick response. Any idea how to include all the sub/parent and so on categries to? I realized right now it only shows the main cat...
    – NewUser
    Commented Nov 29, 2014 at 10:42
  • Related: wordpress.stackexchange.com/questions/61915/… Commented May 25 at 5:53

5 Answers 5

13

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 );
2
  • 1
    Any feedback on this? It would be appreciated (and good manners) if you can leave feedback to your open questions. It would not only benefit you, but the other users finding your questions via search engines. Simply abandoning your questions as you did might lead to other users ignoring your questions in future. Please help us (and yourself) to keep this site and your questions constructive. Thanks for understanding :-) Commented Apr 14, 2015 at 6:12
  • Works correct to me. Thanks!
    – FladeX
    Commented Aug 8, 2020 at 7:35
5

step 1: Create or copy content-single.php and create a new file. eg: content-yourCategory.php step 2: Open single.php and replace this get_template_part('content','single'); by the following code

    if(is_category('yourCategory')){
        get_template_part('content','yourCategory');
    }else{
        get_template_part('content','single.php');
    }

The parameter can be Category ID, Category Title, Category Slug or Array of IDs, names, and slugs.

2
  • 6
    in_category() *
    – Avishay28
    Commented Apr 19, 2016 at 9:42
  • Please correct your reply
    – Chris Pink
    Commented Jun 28 at 10:36
4

This is a convenient way of doing that, found here past this code into your function.php

// Custom single template by category
// https://halgatewood.com/wordpress-custom-single-templates-by-category

add_filter('single_template', 'check_for_category_single_template');
function check_for_category_single_template( $t )
{
  foreach( (array) get_the_category() as $cat ) 
  { 
    if ( file_exists(STYLESHEETPATH . "/single-category-{$cat->slug}.php") ) return STYLESHEETPATH . "/single-category-{$cat->slug}.php"; 
    if($cat->parent)
    {
      $cat = get_the_category_by_ID( $cat->parent );
      if ( file_exists(STYLESHEETPATH . "/single-category-{$cat->slug}.php") ) return STYLESHEETPATH . "/single-category-{$cat->slug}.php";
    }
  } 
  return $t;
}

for more info check out https://halgatewood.com/wordpress-custom-single-templates-by-category

1
function get_custom_cat_template($single_template) {
   global $post;

      if ( in_category( 'category-name' )) {
         $single_template = dirname( __FILE__ ) . '/single-template.php';
      }
   return $single_template;
}

add_filter( "single_template", "get_custom_cat_template" ) ;
0

OLD SOLUTIONS ARE NOT WORKING FOR THE NEW WORDPRESS TEMPLATES (BLOCK TEMPLATES)?

For those who are coming here from google after 2022:

If you are working with block templates, the new template system for WP, that template files are not .php files but just .html files including blocks codes, you can use this answer:

Just create single-post-[category slug]-article.html. It works.

More precisely, this is the order for block template files, WP searchs for the single post:

  1. single-post-[category slug]-article.html
  2. single-post.html
  3. single/html
1
  • Doesn't work on 6.6.2
    – th00ht
    Commented Sep 24 at 8:01

Your Answer

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

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