I'm trying to optimize an e-commerce category system with unlimited category depth (barring system memory limitations). I retrieve all the categories at once and order them as a multi-dimensional array that roughly looks like:
[array] (
[0] (
'CategoryId' => 1,
'ParentCategoryId' => 0,
'Title' => 'Category A',
'SubCategories' => [array] (
[0] (
'CategoryId' => 2,
'ParentCategoryId' => 1,
'Title' => 'Category B',
'SubCategories' => [array] (
[0] (
'CategoryId' => 3,
'ParentCategoryId' => 2,
'Title' => 'Category C'
)
)
)
)
)
)
Each item in the array is actually an object, but for simplicity I wrote it out kind of like an array format.
I'm able to traverse my tree downwards using this function:
/**
* Find Branch using Recursive search by Object Key
* @param String Needle
* @param Array Haystack
* @return Array
*/
public static function findBranchByKey($key, $needle, $haystack)
{
foreach ($haystack as $item)
{
if ( $item->$key == $needle || ( is_object($item) && $item = self::findBranchByKey($key, $needle, $item->SubCategories)) )
{
return $item;
}
}
return false;
}
This finds the object with a matching key and returns it (which may contain more subcategories).
My issue is figuring out how to traverse the other direction. For example, using the data above, let's say I am displaying "Category C" and want to create bread crumbs of it's parents. I can't think of a good way to take my tree array, jump to a specific subcategory, then iterate upwards to get each parent. A resulting array from something like this could be like this so it's easy to spit them out as bread crumbs:
array( 'Category A', 'Category B', 'Category C' )
I could probably do this using SQL in my database but I'd like to retrieve the tree once, cache it, and perform traversal on that object whenever I need to rather than making tons of queries.
TL;DR; How can I traverse upwards in a multidimensional array of categories?
It can be done by recursion.
Let's say, this function should work:
function getPath($id, $tree, &$path = array()) {
foreach ($tree as $item) {
if ($item['CategoryId'] == $id) {
array_push($path, $item['CategoryId']);
return $path;
}
if (!empty($item['SubCategories'])) {
array_push($path, $item['CategoryId']);
if (getPath($id, $item['SubCategories'], $path) === false) {
array_pop($path);
} else {
return $path;
}
}
}
return false;
}
This:
$data = array(
array(
'CategoryId' => 10,
'ParentCategoryId' => 0,
'SubCategories' => array(
array(
'CategoryId' => 12,
'ParentCategoryId' => 1,
'SubCategories' => array()
),
)
),
array(
'CategoryId' => 1,
'ParentCategoryId' => 0,
'SubCategories' => array(
array(
'CategoryId' => 2,
'ParentCategoryId' => 1,
'SubCategories' => array()
),
array(
'CategoryId' => 3,
'ParentCategoryId' => 1,
'SubCategories' => array()
),
array(
'CategoryId' => 4,
'ParentCategoryId' => 1,
'SubCategories' => array(
array(
'CategoryId' => 5,
'ParentCategoryId' => 4,
'SubCategories' => array()
),
)
)
)
)
);
$result = getPath(5, $data);
print_r($result);
will result in:
Array ( [0] => 1 [1] => 4 [2] => 5 )
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.