0

I'm current using the following code to echo the categories of my post :

<?php foreach((get_the_category()) as $category) { echo $category->cat_name . ' '; } ?> 

So, for example, I have post with a parent category HOBBIES and a sub category MUSIC. When this code is used, it is displayed as

MUSIC HOBBIES

While I want to display it as,

HOBBIES MUSIC

How can i achieve this? BTW, the cat id for hobbies is 7 and cat id for jazz is 8.

1 Answer 1

1

This is a tricky and interesting one. It would be pretty easy to write hardcoded orders for a whitelist of categories, but a true ordering algorithm - which will handle an arbitrary number of categories, and an arbitrary tree depth - requires recursion. What follows probably is not the most efficient solution possible, but it works to order a list of categories of no matter what length or depth:

$categories = get_the_category();

// Assemble a tree of category relationships
// Also re-key the category array for easier
// reference
$category_tree = array();
$keyed_categories = array();

foreach( (array)$categories as $c ) {
    $category_tree[$c->cat_ID] = $c->category_parent;
    $keyed_categories[$c->cat_ID] = $c;
}

// Now loop through and create a tiered list of
// categories
$tiered_categories = array();
$tier = 0;

// This is the recursive bit
while ( !empty( $category_tree ) ) {
    $cats_to_unset = array();
    foreach( (array)$category_tree as $cat_id => $cat_parent ) {
        if ( !in_array( $cat_parent, array_keys( $category_tree ) ) ) {
            $tiered_categories[$tier][] = $cat_id;
            $cats_to_unset[] = $cat_id;
        }
    }

    foreach( $cats_to_unset as $ctu ) {
        unset( $category_tree[$ctu] );
    }
    $tier++;
}

// Walk through the tiers to order the cat objects properly
$ordered_categories = array();
foreach( (array)$tiered_categories as $tier ) {
    foreach( (array)$tier as $tcat ) {
        $ordered_categories[] = $keyed_categories[$tcat];
    }
}

// Now you can loop over them and do whatever you want
foreach( (array)$ordered_categories as $oc ) {
    echo $oc->cat_name . ' ';
}

Note that, if get_the_category() returns multiple categories with the same parent, this algorithm treats them the same (which is to say that they are placed in the same order in which get_the_category() returns them).

2
  • doesn't work. i get an error "Warning: Invalid argument supplied for foreach()". Commented Mar 24, 2012 at 16:14
  • 1
    That warning is not what's causing it not to work; the warning just means that somewhere along the line, an array is ending up empty. I have amended the code above so that the warning should be avoided, but I'm afraid you'll have to do more meaningful debugging in order for me to give you a better sense of where things are going wrong. Commented Mar 24, 2012 at 16:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.