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' );

29 thoughts on “Force sub-categories to use the parent category template

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

  2. Spezielles WordPress-Template für ein bestimmtes Kategorie- oder Schlagwort-Archiv | perun.net

    • 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.

  3. 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.

    • 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.

  4. 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' );
    
  5. Thanks for the snippet. Really useful. How would you modify the code to use it with custom taxonomy instead of default categories?

    • 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?

  6. 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.

  7. WordPress-Newsletter Nr. 137 | perun.net

  8. 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

Leave a Reply