Making child categories recognize parent displays

March 14, 2009

As I’ve mentioned in this post, this code is old. It’s been brought to my attention over the last few months that it has issues with newer versions of WordPress. it works fine for 2.0.x-2.7.x, but you shouldn’t be running those versions, and apparently it breaks down with 2.8.x+. The known issues i’ve been made aware of thus far:

  • The RSS feed is damaged/nonfunctional.
  • If you are using Custom fields, they will cease to work.

There are better methods with the newer versions of WordPress – in fact most of what this code does is already built into WordPress, provided you use the right code. Due to the information I’m getting, I’ll be writing a post soon that will give you an alternative (and easier/better/cleaner) method to the function below.

The unfortunate thing is, it’s almost Christmas, and I will be leaving soon to visit my family back home in West Virginia. So I probably won’t be able to offer up this new/improved alternate until after I return. I will try to get it up sooner – but I cannot guarantee it!

Thanks for your patience and support, all! Have a happy holiday, and a Happy New Year!

– December 19, 2009

One thing that WordPress 2.7.x has done is allow you to select what template file you’d like to use for Pages on your site. Instead of doing the old methods of using conditionals, or creating a separate template file every time you create a new Page, you can create a handful of template files and just choose what template you want that Page to use. It’s very nice.

But what happens with Categories?

There are a couple of plugins out there that allow your site to see what Parent categories are, and if they are using their own template file. For example, if you have a category named “Fish”, and the ID is “4″, then typically, to get that category to display it’s own design, you have to either use a conditional:


<?php if(is_category('4')) {

or create a separate filed called “category-4.php” for it to be utilized. The problem is that if you want other categories to use that same template, you either have to manually add in that ID to the conditional, or copy the “category-4.php” template file and rename it to match the new category. This is especially annoying if, for example, you want ALL children, grandchildren and great-grandchildren (all the way down) to have the same design/layout as the top-level parent. Every time you add a new sub-category, you have to manually edit the files to reflect that change.

So, I’m a big fan of writing my own functions. If I can do something with a function, I’d much rather write my own than use a plugin, because writing your own custom functions makes for better customization (and better understanding of what’s going on). You just end up with more options. So this tutorial/tidbit of info is based on yet another piece of code that you can place in your functions.php file.

The problem I mentioned above can be solved with a couple of plugins. However, the ones I’ve found only fix the issue with parent-child relationships. if you bring in a grandchild, you’re back to square one.

However, I have a solution for you :)

Now, this is a function I grabbed from the WordPress forums a long time ago. i truly do not remember who originally wrote this – but I suspect it was “Otto42″. It also could have been “MichaelH.” I wish I had made note of it before (and since I’ve discovered how useful this bit of code it, I’ve now made it standard practice to note where I got it – but in this case, I did not.) because whoever wrote the original really did an awesome thing here – it’s very useful. So whoever it was – you are awesome, and you deserve credit – and you should post a comment here and take it :)

So what you need ot do is open up your functions.php file, and add in this bit of code:


function inherit_template() {
if (is_category()) {
$catid = get_query_var('cat');
if ( file_exists(TEMPLATEPATH . '/category-' . $catid . '.php') ) {
include( TEMPLATEPATH . '/category-' . $catid . '.php');
exit;
}


$cat = &get_category($catid);
$parent = $cat->category_parent;
while ($parent) {
$cat = &get_category($parent);
if ( file_exists(TEMPLATEPATH . '/category-' . $cat->cat_ID . '.php') ) {
include (TEMPLATEPATH . '/category-' . $cat->cat_ID . '.php');
exit;
}


$parent = $cat->category_parent;
}
}
}


add_action('template_redirect', 'inherit_template', 1);

Basically, what the above does is look to see what category you’re in, and then it pulls the template set for that particular category (if there is one set) and uses that for the children of that category. This works for children all the way down – so if you have many sublevels, then it will, indeed, use the same template file for great-great-great-grandchildren of a category. If you have the same layout for all of these categories, then you’re set. Just create that “category-4.php” file, make your layout, stick this code in your functions.php file, and you’re good to go.

But now we have a small catch. I discovered said catch while I was creating the theme for my upcoming CakeShop plugin (no, you can’t see it yet. Not unless you find it :) ) i wanted the children of my “shop” category to have a different layout than all other categories on the site. But I would be using a query for the subcategories, so that the proper amount of posts were being shown (my blog was set to 3 posts shown, but I wanted my shopping section to show 9 at a time – thus a query was necessary to pull this off.)

Because I was using pagination (and we all know what using query_posts does to “next posts” and “previous_posts” links), when I applied the queries, my children were also inheriting the query – so the layout was working fine (using the correct category template), but it was also using the top-level query – so ALL of my subcategories were displaying the same page as my top-level.

So here’s what I had to do: I had to have the template file ask “what category is being queried?” and use that category ID to pull in the correct post information. So within my “category-4.php” file, I added this:


<?php $catid = get_query_var('cat');
$category = get_category($catid);
$cat = $category->cat_ID; // grabbing the requested category ID
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1; // fixing the pagination issue
query_posts('cat=' . $cat . '&showposts=6&paged=' . $paged); // getting the right posts for the category we're in
$wp_query->is_archive = true; $wp_query->is_home = false; // more pagination fixing
if (have_posts()) : while (have_posts()) : the_post(); ?>

Now we have inherited the template for the correct look, AND we are pulling in the proper posts for the category we were in AND the pagination issues are also repaired.

All with a couple of snippets of code, and now we’re set on “automatic.”

Hope this helps someone else out :)

View Comments

Thanks…. This worked! I have searched long to get a working code.

Hi there, I’m getting this yucky error:

Warning: Cannot modify header information – headers already sent by (output started at /nfs/c04/h01/mnt/60194/domains/insidenewyork.com/html/wp-content/themes/insideny/functions.php:8) in /nfs/c04/h01/mnt/60194/domains/insidenewyork.com/html/wp-includes/pluggable.php on line 865

Thanks for any help.

Best,
Lara

All fixed actually! There were extra spaces around my < ? tags in my function file.

All I can say is a big thank you! This is just EXACTLY what I was looking for. I hope that newer WordPress releases add this helpful snippet to their original code.

thank you, thank you!

Sorry, comments are now closed on this post. You may thank the spammers for that one. But if you have any questions, please feel free to email me and ask - maybe it'll make for a good update in a future post. :)