2

I have problem.

<?php query_posts('category_name=events&posts_per_page=2&offset=1'); ?>
<?php while (have_posts()) : the_post(); ?>
<div>
<?php $children = get_categories('child_of=3');
foreach ($children as $child) {
    $child = get_category($child);
    echo $child->cat_name;
}; ?>
</div>
<?php endif; ?>
<?php endwhile; ?>

I would like to show the current subcategory name from any parent category.

With this I only manage to output all the subcategory names from the specified parent...

I didn't use the_category() because it outputs the subcat names wrapped in a list and I would like them to be without any markup.

  • I don't understand your question. "I am within the Loop. I would like to show the current subcategory name from any parent category". What do you mean? – Pieter Goosen May 29 '14 at 11:59
  • I edited the post. – user52339 May 29 '14 at 12:08
  • So you need to display all sub-categories from all parent categories. I can't understand your loop though. And why are you using query_posts here – Pieter Goosen May 29 '14 at 12:14
  • 1
    I strongly recommend against using query_posts, you must not use it, use get_posts, pre_get_posts, or WP_Query instead – Tom J Nowell Jun 3 '14 at 12:26
  • 2
    Also can you rephrase your question a little? It's difficult to figure out what kind of template you're using this in, if you want to use it inside or outside the loop, please provide examples and additional context – Tom J Nowell Jun 3 '14 at 12:29
5

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

First of all, you should not be using query_posts to run custom queries. From the codex itself

Note: This function isn't meant to be used by plugins or themes. As explained later, there are better, more performant options to alter the main query. query_posts() is overly simplistic and problematic way to modify main query of a page by replacing it with new instance of the query. It is inefficient (re-runs SQL queries) and will outright fail in some circumstances (especially often when dealing with posts pagination). Any modern WP code should use more reliable methods, like making use of pre_get_posts hook, for this purpose.

You should be using WP_Query for this custom query

$args = array(
   'category_name' => 'events',
   'posts_per_page' => 2,
   'offset' => 1
);

 $myquery = new WP_Query( $args );

 while ($myquery->have_posts()) : $myquery->the_post();

 <-----YOUR LOOP CONTENTS----->

endwhile;

wp_reset_postdata();

EDIT 1 & EDIT 2

--SCRAPPED--

EDIT 3

Here is a work around of the code from wp_list_categories().

You first need to get the parent category's ID using get_the_category()

$categories = get_the_category();
$parentid = $categories[0]->category_parent;

This parent ID can then be passed back to wp_list_categories() to only show the child categories of that specific parent. If no child category exists, it will return the parent category name, otherwise if the parent have children, the child categories will be returned

Here is the complete function

<?php 
$taxonomy = 'category';

// get the term IDs assigned to post.
$post_terms = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) );
// separator between links
$separator = ', ';
$categories = get_the_category();
$parentid = $categories[0]->category_parent;

if ( !empty( $post_terms ) && !is_wp_error( $post_terms ) ) {

    $term_ids = implode( ',' , $post_terms );
    $terms = wp_list_categories( 'title_li=&style=none&echo=0&child_of=' . $parentid . '&taxonomy=' . $taxonomy . '&include=' . $term_ids );
    $terms = rtrim( trim( str_replace( '<br />',  $separator, $terms ) ), $separator );

    // display post categories
    echo  $terms;
}
?>
  • I tried the code for displaying the subcategory. There is a dot in the last loop that produces an error. After cleaning that dot out, I see the result is the same: all the subcategories names are displayed. Third, is declaring $post_child_cat necessary? P.s. Thank you, I replaced the custom query bit. – user52339 May 29 '14 at 13:45
  • Did you get it working? – Pieter Goosen May 29 '14 at 16:37
  • Now the code outputs the categories, thank you, but the parent category is also shown... – user52339 May 29 '14 at 20:37
  • I tried the code below EDIT2, but it still outputs parent and subcategory – user52339 May 30 '14 at 15:45
  • I have another work around that should do the trick now. I hope EDIT 3 will do want you need. – Pieter Goosen Jun 2 '14 at 14:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy