Showing current subcategory

I have a suspicion that you’ve fallen into a misunderstanding a lot of new users fall into, but rarely realise.

I suspect you have done this:

a screenshot with the parent and child categories selected at the same time

This is bad, and suggests a lack of understanding about how categories work. It will also cause issues in your code when your assumptions don’t match the reality of things. But don’t worry, everyone makes this mistake ( myself included ).

For example, we don’t tell people that a house is also a building, they already know that houses are a type of building, and we don’t have to mention to people that cats and dogs are animals for them to know, in the same way that you don’t need to tell WordPress that your post is in the ‘event’ category if it’s already in the sub category ‘conference’ or ‘interest group’, because it already knows that the ‘event’ category contains those.

What should have been done is this:

a screenshot showing only the child category

Here, even though I’ve only ticked the child category, any posts under child, will also appear inside the parent category archives, because ‘parent’ contains ‘child’.

Child categories are not descendants of parent categories. Child categories are contained by parent categories.

So in your case, you grab the current category of the post, running into these issues:

  • You mention the category the post is in, but a post can be in multiple categories, not a single category
  • You assume the category you grabbed is the child category, but you ticked the parent category too, so it’s probably the parent category you’ve grabbed, the child category is the next one
  • You’ve assumed it’s the child category, but it isn’t, and now you’re trying to find the parents parents category and failing because there isn’t one.

What you need to do:

  • Stop using query_posts, seriously, make your editor scream klingon at you when you type it, have a USB toy fire foam missiles at you, make your desktop wallpaper a pool of blood, never use it. You have no excuses for using it. None.
  • Stop checking every term up the whole hierarchy, just check the sub category you want. Categories contain all their sub categories, not just the ones that checked that specific box.
  • Posts have multiple categories, even without the parent/subcategory thing, be careful
  • foreach loops don’t require a semicolon on the end

So the code

This is you current code:

$children = get_categories('child_of=3');
foreach ($children as $child) {
    $child = get_category($child);
    echo $child->cat_name;
}

This will list out all the category names. In our example with the parent and child categories checked, it will print out this:

parentchild

First lets use a better function, that’s more generic, and handle tags and custom taxonomies:

$categories = wp_get_object_terms( get_the_ID(), 'cat');

Then you have to check that the post actually has categories:

if(!empty($categories)){

And that it wasn’t an error:

    if(!is_wp_error( $categories )){

So loop over your terms, lets put them in a nice list:

        echo '<ul>';
        foreach($product_terms as $term){

Print them out:

            echo '<li><a href="'.get_term_link($term->slug, 'product').'">'.$term->name.'</a></li>'; 

and close the loop:

        }
        echo '</ul>';
    }

}

This gives you a full list of all the categories on a post. Now for the part you’re having issues with. You only want to show sub categories. So we need to check if the category is a sub category before showing it, which you don’t do.

So:

echo the term

Becomes:

if the term has no parent
    echo the term

You can check if a term has a parent by doing:

if ( $term->parent != 0 ) {

You also have a problem you’re unaware of, what if I have 3 levels of categories rather than 2? What about sub-sub-categories? To handle that, perhaps you only want to show the bottom-most level, or only show sub categories and not sub-sub-categories. To do that you’ll need to know if a category term has children.

You can also check if a term has children by doing:

if ( !empty( $term->children ) ) {

I leave the assembly of the final code as a task for the reader, but if you understand what has been said, you will understand what needs to be done ( and which lines to copy paste where ).

This won’t fix users checking both categories, so you have to watch out for that. Ways of getting around that include preventing users from checking the parent category by using a custom radio box UI instead of the standard checkbox UI.

This is also why a category archive also contains all the posts in the sub categories.

Glossary

  • Taxonomy – a system of classifying things, e.g. category, tag, colour, caste, shape
  • Term – a classifier in a taxonomy, e.g. ‘red’ is a term in the ‘colour’ taxonomy, ‘pants’ are a term in a ‘clothing’ taxonomy, ‘cat’ is a term in a ‘animal’ taxonomy, or ‘pop’ is a term in the ‘music genre’ taxonomy. Note that a term is not a thing itself, for example, pop songs belong in the ‘pop’ term of the ‘music genre’ taxonomy
  • Category and Tags – two built in taxonomies that come with WordPress
  • Object – something that fits into a taxonomy term, normally posts, but users and comments can also be placed into terms and taxonomies

Leave a Comment