Reputation: 77
I have a an array of products. Each product contains its category and subcategories listed in a hierarchical order:
Array ( [product_id_1] => Array ( [0] => Men [1] => Sunglasses [2] => Luxury [3] => Ray-ban ) [product_id_2] => Array ( [0] => Women [1] => Lenses [2] => Casual [3] => Gucci ) [product_id_3] => Array ( [0] => Men [1] => Sunglasses [2] => Casual [3] => Prada ) [...] )
I want to create an unordered hierarchical HTML menu like so:
-Men --Sunglasses ---Luxury ----Ray-ban ---Casual ----Prada -Women --Lenses ---Casual ----Gucci
The function should strip out repetitive categories and subcategories. This script returns the array of products that I've posted at the top:
<?php
function displayNestedMenu( $posts, $taxonomies ) {
foreach ( $posts as $post ) {
foreach ( $taxonomies as $key => $taxonomy ) {
$push = wp_get_object_terms( $post->ID, $taxonomy );
if ( !empty( $push ) ) {
$list[$post->ID][] = $push[0]->name;
}
}
}
return $list;
}
print_r( displayNestedMenu( $posts, $taxonomies ) );
?>
I imagine the solution should invoke the function inside the function but after trying a couple of methods I haven't succeeded yet. Any suggestions are appreciated!
Upvotes: 1
Views: 1391
Reputation: 2204
Here is a simple idea :
$array = array(
'product_id_1' => array(
'Men',
'Sunglasses',
'Luxury',
'Ray-ban'
),
'product_id_2' => array(
'Women',
'Lenses',
'Casual',
'Gucci',
),
'product_id_3' => array(
'Men',
'Sunglasses',
'Casual',
'Prada'
)
);
The idea is to recreate the keys depending on the parent category, after that we sort them using ksort():
function tree($array){
$newArray = array();
foreach ($array as $arr) {
foreach ($arr as $key => $row) {
if ($key > 0) {
$index = array();
for ($i = 0; $i <= $key; $i++)
$index[] = $arr[$i];
$index = implode('_', $index);
} else
$index = $row;
$newArray[$index] = $row;
}
}
ksort($newArray);
return $newArray;
}
Then display the HTML :
$products = tree($array);
$i = 0;
echo '<ul style="list-style-type:none">';
foreach ($products as $key => $row) {
if(strcmp($row, $key) == 0 && $i != 0)
echo '</ul><br><ul style="list-style-type:none">';
++$i;
$level = count(explode('_', $key));
$padding = 15 * (--$level);
echo
'<li style="padding-left:' . $padding . 'px">
<span style="border-left:1px dashed black;border-bottom:1px dashed black;"> ' . $row . '</span>
</li>';
}
echo '</ul>';
Upvotes: 1
Reputation: 3848
You could transform the array in a static way, as the structure you describe always has four parts;
$hierarchy = array();
foreach($products as $product_id => $product) {
list($gender, $category, $type, $brand) = $product;
$hierarchy[$gender][$category][$type][$brand][] = $product_id;
}
Upvotes: 0
Reputation: 356
PHP has powerful array features: string-indexed arrays can help provide solutions to problems like this one.
For the array conversion step:
$hrchy=array();
foreach($products AS $product){//$products is as per your first array, at start…
hrchy_ins($hrchy,$product);
}
function hrchy_ins(array &$hierarchy,array $product){//$hierarchy should be passed by reference…
if(\count($product)>0){//Condition necessary to implement base case, avoiding infinite recursion
if(!isset($hierarchy[$product[0]])){$hierarchy[$product[0]]=array();}//Conditional execution ignores duplicates…
if(\count($product)>1){hrchy_ins($hierarchy[$product[0]],\array_slice($product,1));}//Condition may not be strictly necessary (see condition above!)
} }
We might now use a recursive approach for a further HTML-writing step (the recursion secret sauce = a simple recursive function including a branch-on-condition for the base-case):
function prod_list(array $hierarchy){
if(\count($hierarchy)===0){
return '';
}else{
$list='';
$list.='<ul>';
foreach($hierarchy AS $cat => $children){
$list.='<li>'.$cat;
$list.=prod_list($children);//Recursive step…
$list.='</li>';
}
$list.='<ul>';
return $list;
}
}
Finally, after defining the function, we invoke it:
echo(prod_list($hrchy));
Disclaimer: I have not tested this code.
Upvotes: 1