Force sub-categories to use the parent category template

A couple of times in the last several years, I’ve needed sub-categories to inherit their parent’s archive template, but it’s just not something the Template Hierarchy supports. I’ve seen several plugins that tried and failed to do it, so finally I wrote a little filter that in my testing, works any number of levels deep, from sub-sub-categories to sub-sub-sub-categories. Enjoy!


function new_subcategory_hierarchy() {	
	$category = get_queried_object();

	$parent_id = $category->category_parent;

	$templates = array();
	
	if ( $parent_id == 0 ) {
		// Use default values from get_category_template()
		$templates[] = "category-{$category->slug}.php";
		$templates[] = "category-{$category->term_id}.php";
		$templates[] = 'category.php';		
	} else {
		// Create replacement $templates array
		$parent = get_category( $parent_id );

		// Current first
		$templates[] = "category-{$category->slug}.php";
		$templates[] = "category-{$category->term_id}.php";

		// Parent second
		$templates[] = "category-{$parent->slug}.php";
		$templates[] = "category-{$parent->term_id}.php";
		$templates[] = 'category.php';	
	}
	return locate_template( $templates );
}

add_filter( 'category_template', 'new_subcategory_hierarchy' );

27 Comments

  1. Wow wow wow. Thanks so much. It saved me.

  2. Just what I was looking for! Thanks.

  3. That’s a great tip! Thank you for sharing!

  4. Thanks. It works perfectly. I also have another similar problem, how do force the sub page to use its parent page template?

  5. Thanks for this! Worked perfectly. What plugin are you using for you social commenting?

  6. Do you also know how to get a category to use the body class of it’s parent category?

    • Drew Jaynes

      September 5, 2013 at 3:11 pm

      If you’re using post_class() or body_class(), I’d just write a filter callback to add the parent class and then do add_filter() with ‘body_class‘ or ‘post_class‘ as the hook, and call the callback inside new_subcategory_hierarchy() or whatever.

  7. Tried this but it didn’t work.

    function body_class_add_parent_category( $classes ) {

    if ( is_category() ) {
    $category = get_the_category();
    $parent = $category[0]->category_parent;
    $class = get_cat_name($parent);
    } return $classes;
    }
    add_filter( ‘body_class’, ‘body_class_add_parent_category’ );

    Not quite sure what’s wrong here. Any suggestions are appreciated.

    • Drew Jaynes

      September 5, 2013 at 3:33 pm

      First off, remember that $classes is an array. So you’d want to assign the returned value of get_cat_name( $parent ) with something like

      function body_class_add_parent_category( $classes ) {
      
      	if ( is_category() ) {
      		$category = get_the_category();
      		$parent = isset( $category[0]->category_parent ) ? $category[0]->category_parent : '';
      		$classes[] = get_cat_name( $parent );
      	}
      	return $classes;
      }
      add_filter( ‘body_class’, ‘body_class_add_parent_category’ );
      

      Note that $class became $classes[]. Also, I added an isset() ternary to avoid a notice.

  8. Thanks again for your help. Just learning php. This looks good but for some reason it’s not adding the parent category body class. I used the script below for single posts. This worked perfectly but I was not able to adapt it for child categories. Any thoughts?

    <?php
    // Add categories to body class on Posts
    function body_class_add_categories( $classes ) {
     
    	// Only proceed if we're on a single post page
    	if ( !is_single())
    		return $classes;
     
    	// Get the categories that are assigned to this post
    	$post_categories = get_the_category();
      
    	// Loop over each category in the $categories array
    	foreach( $post_categories as $current_category) {
     
    		// Add the current category's slug to the $body_classes array
    		$classes[] = 'category-' . $current_category->slug;
     
    	}
    	
    	foreach( $post_categories as $current_category) {
     
    		// Add the current category's slug to the $body_classes array
    		$classes[] = 'category-' . $parent_category->slug;
     
    	}
     
    	// Finally, return the $body_classes array
    	return $classes;
    }
    add_filter( 'body_class', 'body_class_add_categories' );
    
  9. Thanks dude!!! This is butter.

  10. Thanks for the snippet. Really useful. How would you modify the code to use it with custom taxonomy instead of default categories?

    • Drew Jaynes

      November 28, 2013 at 8:22 pm

      Hi Petr,

      Something like the following should work for hierarchical taxonomies (untested):

      /**
       * Filter the taxonomy hierarchy to inject a parent level of templates.
       * 
       * @param string $template The current template.
       * @return string Filtered taxonomy template.
       */
      function new_tax_hierarchy( $template ) {
      	$term = get_queried_object();
      
      	// If not an object, or the object doesn't have a taxonomy, bail.
      	if ( ! is_object( $term ) || ! isset( $term->taxonomy ) )
      		return $template;
      
      	$taxonomy = $term->taxonomy;
      
      	// If the taxonomy isn't hierarchical, bail.
      	if ( ! is_taxonomy_hierarchical( $taxonomy ) )
      		return $template;
      
      	$templates = array();
      	$parent_id = $term->parent;
      
      	if ( 0 == $parent_id ) {
      		// Use default values from get_taxonomy_template().
      		$templates[] = "taxonomy-$taxonomy-{$term->slug}.php";
      		$templates[] = "taxonomy-$taxonomy.php";
      		$templates[] = 'taxonomy.php';
      	} else {
      		$parent = get_term( $parent_id, $taxonomy );
      
      		// Current templates.
      		$templates[] = "taxonomy-$taxonomy-{$term->slug}.php";
      		$templates[] = "taxonomy-$taxonomy.php";
      
      		// Parent templates.
      		$templates[] = "taxonomy-$taxonomy-{$parent->slug}.php";
      		$templates[] = "taxonomy-$taxonomy-{$parent->term_id}.php";
      		$templates[] = 'taxonomy.php';
      	}
      	return locate_template( $templates );
      }
      add_filter( 'taxonomy_template', 'new_tax_hierarchy' );
      
      • Thanks for your reply, really appreciate your help.

        I have tried your function, but it still doesn’t work. Here is what I am trying to achieve:

        Render all products with producttype (kitchen, bathroom) taxonomy using this template:
        taxonomy-producttype.php (works fine)

        Render all products in kitchen category using this template:
        taxonomy-producttype-kitchen.php (works fine)

        Render all products in kitchen subcategories using this template:
        taxonomy-producttype-kitchen.php (but it currently renders as taxonomy-producttype.php)

        Any thoughts?

  11. Thanks Drew! It worked for me. I tried several other code snippets from other sites as well, but they didn’t work. But this one worked at first go! :)

  12. You save me mate! Thanks!!!!!!!!!!

  13. Thank you ! It’s perfect. :)
    Unfortunately, it doesn’t take sub sub category as you said. Then i make this :

    $category = get_queried_object();
    $temp = $category;
    
    do {
    	$parent_id = $temp->category_parent;
    	$temp = get_category( $parent_id );
    } while ( $temp->category_parent );
    

    instead of :

    $category = get_queried_object();
     
    $parent_id = $category-&gt;category_parent;
    

    Have a nice day.

  14. thanks a lot for this great tutorial……….

  15. I tried using this code to show a single post for a particular category name- products but it does not work for me. Somehow it picks the single.php file and not the category-products.php

    I am new to php functions kindly help me achieve different templates for different category & its sub-category should also show the layout of its parent’s category template

  16. Excellent one. Saved me from perishing… :)
    Thanks a lot.
    Shared on WPSE: http://wordpress.stackexchange.com/a/145886/22728

  17. I love you.

  18. Thanks Drew! I tried a few other snippets before I found yours, and none of them worked quite right. This is perfect!

Leave a Reply

© 2014 WerdsWords

Theme by Anders NorenUp ↑