Skip to main content
added 62 characters in body
Source Link
Boone Gorges
  • 3.5k
  • 1
  • 19
  • 14

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).

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:

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

foreach( $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( $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( $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).

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).

Source Link
Boone Gorges
  • 3.5k
  • 1
  • 19
  • 14

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:

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

foreach( $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( $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( $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).