Category Template Hierarchy

Category Template Hierarchy – WordPress Plugin ( Download )

Note: This page is out of date, please review the documentation in the ‘Description’ and ‘Other Notes’ area of this plugin’s WordPress Plugin Directory page.

Adds parent-category.php and child-category.php with all the normal hierarchical behavior of the native category templates. This greatly extends the natural hierarchy of theme templates with regard to categories. Theme developers can now easily create separate templates for categories with have children, the children themselves, and categories which are neither.

Also adds is_parent_category() and is_child_category() functions for easy use in themes.

Note: This plugin does not actually create parent-category.php, child-category.php or any of their related templates – rather it modifies the native [template hierarchy]( to allow theme developers to create specific templates for parent and child categories

Developer Notes: Template Hierarchy

What follows are the lists by which the new hierarchical elements will cascade – realize that all these lists are essentially just branches off of the existing Template Hierarchy.

If category has no children and has no parent (stand-alone category):

  • category-{slug}.php
  • category-{term_id}.php
  • category.php
  • archive.php
  • index.php

If category is a parent (has children):

  • parent-category-{slug}.php
  • parent-category-{term_id}.php
  • parent-category.php
  • category.php
  • archive.php
  • index.php

If category is a child (has a parent):

  • child-category-{slug}.php
  • child-category-{term_id}.php
  • child-category.php
  • category.php
  • archive.php
  • index.php

Developer Notes: Conditional Tags

With this plugin comes two additional conditional tags which behave much like any other in WordPress. In a similar fashion to how one might use is_category(), developers may, with this plugin, use the following functions:

  • is_parent_category()
  • is_child_category()


These conditional tags checks if the page being displayed is for hierarchical category that has children (e.g. is a parent category), or has a parent (is a child) respectively. They are boolean functions, meaning they return either TRUE or FALSE.




$category (integer/string/object) (optional) Category ID, Category Slug, Category Object. Default: Current Category

Note: Unlike is_category(), these functions will not take arrays of categories or category titles. I’ll work on that. Sorry.

Return Values

(boolean) True on success, false on failure.


 is_parent_category() is_child_category()  // When any parent/child category archive page is being displayed  is_parent_category( '9' ); is_child_category( '9' ); // When the archive page for Category 9 is being displayed AND its a parent/child. is_parent_category( 'blue-cheese' ); is_child_category( 'blue-cheese' ); // When the archive page for the Category with Category Slug "blue-cheese" is being displayed AND its a parent/child. 


  • Clearly there is a need to have is_child_category_of() and is_parent_category_of(). They will be made available in future releases.

Known Bugs

  1. [Fixed] In 1.0 and 1.0.1 there was a “happy accident” which I permitted, wherein if a category was both a parent and a child, it would look for a parent-child-category.php chain of templates. I later realized that in such a case the plugin would only look for that chain, as it would overwrite the previous chain of templates. 1.0.2 eliminated this “happy accident”
  2. [Future fix] Revealed by bug #1, the current logic makes it such that if a category is both a parent and a child, the child relationship will take precedence over the parent relationship. In such a case, only the child-category.php chain of templates will work with for that category.

41 Comments on “Category Template Hierarchy”

  1. I am having trouble getting my posts to the proper tag/catergory on my home page.

    • eddiemoya says:

      You’ll need to provide more detailed explanation of what you need to do and what you’ve tried so far, and the results you’ve seen before I or anyone else can help you.

      Is this a problem with the this plugin or are you just having general development trouble with WordPress tags/categories. If its not a problem with my plugin I may still be able to help you but you might also want to try the other larger avenues for WordPress support such as the WordPress Support Forums, the #wordpress IRC channel, or even the WordPress Hackers Mailing List.

      If you are having trouble with my plugin, make sure to read the documentation I’ve provided with the plugin – its also available at the plugins download mage on (Plugin Description, and Other Notes)

    • Jose says:

      How to do this? I want make my fatrueed post showing up 3 latest fatrueed and on the next loop will not display my showing 3 latest post but display post after fatrueed loop.Please Help me

  2. I am an amateur. I added a page/tab/category to my home page. In wordpress when I added a post, then click on 2012 category, then publish. It is not coming up on my site. When I click on 2012 Rental tab, this message comes up.
    Fatal error: Call to undefined function print_pre() in /home/content/91/5366791/html/wp-content/plugins/category-template-hierarchy/category-template-hierarchy.php on line 78
    Any assistance is much appreciated. All this looks Greek to me.

    • eddiemoya says:

      Well I know exactly whats wrong right off the bat. I’m going to have to make a bug fix and a new version release. Thanks for the report.

      That said, I’m not clear on a couple things regarding your troubles exactly. Are you developing a new theme or modifying an existing theme, or are you just using an existing theme? This plugin is more or less only really useful to theme or plugin developers.

      Either way when I make the patch I will let you know so you can upgrade. Thanks for the bug report.

    • eddiemoya says:

      Go ahead and upgrade to v1.1.1 when you get a chance. This should resolve the error you saw. Thanks again for the bug report.

  3. Meritoni says:

    It pbbaorly should still show up even if you don’t have any posts, so I don’t know what could be wrong and I can’t see anything without a link to your site.

  4. Barnesanger says:

    Hi there!

    When i use this plugin, i cannot use $post->post_content in my template.

    example, it is not working in child-of-category-{slug}.php

    Any idea on how to resolve this?

    • eddiemoya says:

      I don’t seem to be able to reproduce this problem. I just switched out this…

      <div class="post_content">

      …for this…

      <div class="post_content">
          <?php echo $post->post_content; ?>

      … and it seems to work just fine.

      The plugin does basically the same thing that WordPress does by default in that is uses get_query_template(), which eventually calls load_template();. It is load_template(); which pulls $post, $posts, and a bunch of other things into scope just before loading the template – so there’s no reason it would not be in scope unless something else is tampering with it.

      Not sure what else you’ve got going on, but try doing print_r($post); on that template to see if you even have $post within your scope – normally you would. If you dont see any output from the print_r, try calling global $post; just before the print_r(); and see if that brings it into scope for you.

      Let me know how this goes, I’d like to know for sure if this is a bug with my plugin or not.

      Good luck.

      Edit: Edited this comment to fix formatting of the code.

      • Barnesanger says:

        Hi there!

        When i add global $post; before the print_r, it works.

        This is my template child-of-category-test.php and the posts are in category test->test2

        Any ide why i need to do global $post; before?

      • eddiemoya says:

        I have not had a chance to look at this yet – I will try to reproduce you circumstances. For know just call $post in from the global scope. Might I ask, why are you using the $post object to get post_content instead of just using the_content()?

  5. Barnesanger says:

    I’am doing a if() to check if the_content() is empty or not. So i need to do if(empty($post->post_content)) because if(empty(the_content())) do not work.

    • eddiemoya says:

      I believe if(empty(get_the_content())) should work just fine. the_content() echo’s the content, get_the_content() returns it.

      Nonetheless, I have to figure out why your not able to use the $post object.

    • eddiemoya says:

      I have found the problem. Monday morning I will release 1.2.1 which should resolve the issue.

      The reason I was not seeing this bug is because I was using get_template_part(), which itself brings $post in from the global scope. This problem is occurring in the first place because I switched from filtering all of ‘template_redirect’ (which broke other parts of the template structure) to filtering just ‘category_template’ which is more specific – but didn’t realize the impact it had on the global scope variables.

      In any case, thanks for the bug report, check back monday for the update.

  6. madn3ss75 says:

    I think you have to add at line 71, just before
    $templates = array_merge($templates, self::add_template_set($template_prefix));
    the following code:
    if (!empty($template_prefix))

    I use a category with no parents and no childs, and without that control, in the function category_template_redirect, the template_prefix was an empty array. This lead to a final templates array with only “archive.php” and “index.php”.

    Hope this helps.

    • eddiemoya says:

      I think you and I found the same problem at the same time. I actually logged into my blog to write a post about the update.

      Try version 1.3.1 – What I’ve done is simply added ‘category.php’ on line 70 – somehow, a couple versions ago I must have deleted that line and never noticed it – so if you were using normal ‘category.php’, it wouldn’t have worked.

      Give it a try, let me know if that solves your problem.

      Thanks for the bug report!

    • Yutaka says:

      From what I understand, I’m supspoed to install this plugin in my existing WP account and then install this in my new WP database and it’ll directly transfer the files over? Is that correct? How long does it take to clone? Do I need to change any config settings in the wp-config.php file?

  7. madn3ss75 says:

    I updated the plugin, but the bug is still living.
    The problem is that I use a custom category template (like category-blog.php), and even in this case if you don’t put the check «if(!empty($template_prefix))» before merging the $templates array, it would result in a loss of the 2 previous entries (category-{slug}.php and category-{id}.php) that was setted before the call to array_merge.

    So that little piece of code is needed even after this update.


    • eddiemoya says:

      Ahh I see what your talking about.

      The problem is actually that the add_template_set() function returns null if $template_prefixes is empty, because it means it never goes through the foreach, and never create the $templates array.

      Adding `$templates = array();` before the foreach fixes it, your way would also do the trick.

      I went ahead an updated once more. We’re now at version 1.3.2 – good job catching this! Go ahead and update, sorry for making you do it twice.

      Some of this is not written so well, I originally had a lot more planned for this plugin, but I’ve scaled down my intentions, so some of the unnecessary complexity will go away soon. (already written most of v2.0, just not ready to release yet).

      Thanks a lot for the report and for pointing me toward the exact problem. I love releasing plugins, and my job lets me release plugins publicly, specifically because of this kind of benefit from the community. Thanks!

      If you don’t mind me asking, what kind of site/project are you use this plugin on?

      • madn3ss75 says:

        First let me say that such a plugin should be included in the core of WordPress, because it offers a basic functionality that should be available by default.
        You’ve done a great job, and I thank you for your effort.
        I’m going to use the plugin for my company web site (I own a web agency), wich will be published in the next few days (maybe tomorrow). I’ll let you know the url, if you want.

        Back to the code, we have once again the same problem.
        If $template_prefixes is passed empty to add_template_set (on line 68), the foreach loop never starts and the $templates var will be returned NULL. That will erase the contents of the $templates array in the category_template_redirect function and the previously inserted items will no longer be available.

        1.3.3 is on its way 🙂

      • eddiemoya says:

        I was about to ask you to verify that you were actually on 1.3.2, because I had added $template = array() before the foreach, so that it returns an empty array instead of null.

        However, I went and looked and somehow I must have screwed up the commit. I’ve re-committed the changes I made in 1.3.2 as v1.3.2.1 – check it out, and let me know how that goes. Thanks for your patience with this.

        I agree it should be in core – I’d like to refine this a lot more in terms of performance and perhaps at some point I may try to commit this as a core patch and see what others think. Thanks again.

      • madn3ss75 says:

        Ok, the latest release works.
        Thank you for your support.

      • eddiemoya says:

        Thanks for the feedback, good luck on your project.

  8. mikethicke says:

    Hi Eddie,

    Here is what I’m trying to do: Have a category template apply to a category and all of its descendants (unless that descendant has a more specific template).

    I have a structure something like this:

    – Astronomy
    — Chronometers
    – Physics
    — Weights
    — Slide Rules

    I thought I’d be able to do this with child-of-category-collections.php, but this appears to only apply to Astronomy and Physics (not Collections, Chronometers, Weights or Slide Rules). Is there an easy way to do this with your plugin?


    • eddiemoya says:

      Hey Mike,

      Thanks for the question. I struggled a bit with regard to how to make this plugin function when I first developed it, and one of the decisions I made was to make child-of-*.php apply only to direct descendants. This is because the intention was to make child-of-*.php a more specific template that category-*.php, not less specific.

      That said, in my last major release, I was going to add new templates to allow for descendant-of-*.php, however I pulled it out because I quickly realized the problem is more complex that I had thought. The only simple solution is to loop through all parent categories all the way to the top, and add them to the list of potential templates. This seems awkward to me, and I didn’t quite know how to place it in terms of specificity, since the number of potential matches was indeterminate. In the end I simply didn’t have time to work out the problem.

      I’ve got functions in this plugin that let you easily determine category relationships, even those like what your asking for. So it may be possible for you to do this from your theme, with the help of this plugin. I’m winging this, and you’ll need to tell me if any of this works, because I don’t really have time to test right now, it should get you started though. Here we go…

      add_filter('cth_category_template', 'descendant_templates');
      * My plugin will call your function, and pass it the list of all templates
      * before sending them off to find which ones match.
      function descendant_templates($templates){
      * The $parents variable is key, this is what I am not able to know
      * from within the plugin.
      * Im assuming you may have more than one top-level like collections.
      * The order given here will determine the hierarchical order, should
      * A particular category be a descendant of more than one of the $parents.
      $parents = array ('collections', 'other-top-level-slug');
      //This will be populated with template names of matched categories
      $desc_templates = array(
      'slugs' => array(),
      'ids' => array()
      foreach($parents as $parent_slug){
      //This function is in the Template Category Hierarchy plugin.
      if(is_child_of_category($parent_slug, null, false)){
      $parent = get_category_by_slug($parent_slug);
      //Collecting slugs and ID's seperately so we can insert them in the right places later
      $desc_templates['slugs'][] = "descendant-of-category-{$parent->slug}.php";
      $desc_templates['ids'][] = "descendant-of-category-{$parent->id}.php";
      * Adding the appropriate elements to the templates array.
      * The position '2' for slugs can be assumbed because if
      * the current category is a descendant of any category, then
      * it will already have the is-child-*.php templates in the
      * list.
      * @uses array_slice();
      * @link
      array_splice($templates, 0, 0, $desc_templates['slugs']);
      array_splice($templates, 2, 0, $desc_templates['ids']);
      return $templates;

      Now that I’ve written this out, this will probably be the most likely solution within the plugin, except I’ll just make the list of parent category slugs filterable.

      Let me know how this goes.

  9. bethsobi says:

    I am taking over management of a site that uses your plugin. the following is showing up on the page instead of giving the information: [resourcelist category=”eba-activity-observations”]

    Can you point me in the right direction to find the problem? Thanks.

  10. bethsobi says:

    I’m managing a site that uses your plugin. The pages are showing the shortcode [resourcelist category=”eba-activity-observations”] instead of actually showing the information. Can you please point me in the right direction to resolve the issue? Thanks. I apologize if this showed up twice, but I hadn’t logged in when I first posted this question and it doesn’t look like it got posted. Thanks. Beth

    • eddiemoya says:

      I dont think I have any plugins that have a shortcode called `resourcelist`. I have one plugin that comes with a shortcode and it is Media Categories, but thats a modified `gallery` shortcode. Since your commenting on this plugin page, I assume your not talking about Media Categories anyway. I do not think that the Category Template Hierarchy could interfere with shortcodes. All it does is allow developers to create more kinds of templates, it doesnt control nor should it effect what is done on those templates. Can you give a little more information about your circumstances?

      • bethsobi says:

        Hi, Eddie.

        I found some code in the page template that refers to a shortcode for resourcelist.

        add_shortcode( ‘resourcefile’, ‘resourcefile_shortcode_handler’ );
        function resourcefile_shortcode_handler( $atts,$content = ” ) {
        //[resourcefile id=””][/resource]

        ), $atts));

        $html = ”;

        $html .= ‘‘;
        $html .= ”;
        $html .= ”.$atts[‘title’].”;
        if($filedescription != ”){
        $html .= ”.$content.”;
        $html .= ‘

        return $html;
        //return print_r($atts,true);

        So maybe this doesn’t have anything to do with your plugin?


      • eddiemoya says:

        It does not appear that this should have anything to do with my plugin. The developer seems to have attempted to create a custom shortcode. The only way would be if the filters im using were echoing instead of returning, but I checked to make sure, and they are returning data properly. What version of the plugin are you running on? Its possible that your running on an outdated version that could have had this problem in the past – its the only way I could see this might be caused by my plugin.

        What you pasted above is how you create a shortcode, but the fact you said was being shown on the page was someone trying to use the shortcode and it failing. I would recommend first, try to use the same shortcode on a page that isnt using a template related to this plugin. For example, try to run the `resourcelist` shortcode on the index.php template – using the `do_shortcode()` function. Assuming the previous developer isnt using any of the public function from my plugin, then you should even be able to turn off my plugin entirely. If the shortcode doesnt work, then theres soemthing wrong with the way the shortcode has been created.

        In any case, I really dont think this is being caused by my plugin but I hope the above helps.

      • bethsobi says:

        We’re using 1.5. The code was working before and the only thing that appears to have changed was a WordPress update. I’ll have to get someone who knows php to see if they can find the issue. Thanks, Eddie.

        Beth Sobiloff

        Birchwood Enterprises


      • eddiemoya says:

        It could be that the way shortcodes need to work changed between those two versions. Again, I would try turning off my plugin and see if its still a problem.

  11. mrmagne says:

    Have you activated the plugin?

  12. bethsobi says:

    I could give you a link to the page, but it has password protection. In the backend there’s a huge list of categories that display information in sort of a slide down when someone clicks on the title of the section. I assumed that your plugin was running this. But instead of the drop down appearing, it just shows the short code. It seemed to happen after someone updated the WordPress version.

  13. ognjen says:


    My name is Ognjen and I’m the owner of FirstSiteGuide where I’m creating tutorials to help people get online in 30 minutes.

    I would love to ask you for permission to translate your Category Template Hierarchy plugin found at and help our readers of different communities to use it in their own language?
    I can translate it to my native Serbian language and have a coworker who can do it in Spanish. But you would need to create the transtlable .pot file first in order for me to proceed.

    Please let me know if you are willing to do that so I can translate it.

    Best Regards,
    Ognjen Djuraskovic

  14. ognjen says:


    Checking again if its alright to translate your plugin?

    Please let me know what you think.
    Ognjen Djuraskovic

    • eddiemoya says:

      Hello Ognjen,

      I think it is fantastic that someone is interested in this plugin enough to put time into translating it. I would be very happy to help make it ready for this. However I am not clear what part of the plugin would need translation. There is no end-user interface for this plugin – its a developers tool only.

      Please advise on what part of the plugin would need 18n, and I’ll do my best to make it happen as soon as I can.

Leave a Reply to eddiemoya Cancel reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s