Reputation: 541
I would like to create a category-tree-array, with unlimited subcategories. Without having to nest foreach loops in foreach loops.
The goal is to have an array of categories in the right order, that I can use for multiple other functions. I need to be able to easily go through this array to find more underlying data. For instance to fetch and later display the (blog, page or product) items that reside in these categories.
It should look something like this:
Array
(
[0] => Array
(
[url] => url_to_cat
[title] => Top Category 1
[depth] => 0
)
[1] => Array
(
[url] => url_to_cat
[title] => Top Category 2
[depth] => 0
)
[2] => Array
(
[url] => url_to_cat
[title] => Sub Category 1 of Category 2
[depth] => 1
)
[3] => Array
(
[url] => url_to_cat
[title] => Sub Category 2 of Category 2
[depth] => 1
)
[4] => Array
(
[url] => url_to_cat
[title] => Sub Category 1 of Sub Category 2
[depth] => 2
)
)
With some help from this and other sites I have come to this function below, wich is in the right direction, but it gets me a multi-dimensional array. That will be difficult for displaying.
The category table has these fields: cat_id, parent_id, title. The url comes from another table, is not really relevant here.
function category_list($category_parent_id = 0) {
static $cats;
if (!is_array($cats)) {
$sql = "SELECT * FROM category";
$result = $db->query($sql);
while ($record = $result->fetch_array()) {
$cats[] = $record;
}
}
foreach ($cats as $cat) {
// if not a match, move on
if ((int) $cat['parent'] !== (int) $category_parent_id) {
continue;
}
$item[$i]['url'] = 'url';
$item[$i]['title'] = $cat['title'];
$item[$i]['children'] = category_list($cat['cat_id']);
$list_items[] = $item;
}
return $list_items;
}
The initial $cats array:
Array
(
[0] => Array
(
[title] => Top Category 1
[parent] => 0
[cat_id] => 1
)
[1] => Array
(
[title] => Top Category 2
[parent] => 0
[cat_id] => 2
)
[2] => Array
(
[title] => Sub Category 1 of Category 2
[parent] => 2
[cat_id] => 3
)
[3] => Array
(
[title] => Sub Category 2 of Category 2
[parent] => 2
[cat_id] => 4
)
[4] => Array
(
[title] => Sub Sub Category 1 of Sub Category 2
[parent] => 4
[cat_id] => 5
)
[5] => Array
(
[title] => Sub Sub Sub Category 1 of Sub Sub Category 1
[parent] => 5
[cat_id] => 6
)
)
I can not get my head arround how to get the children included in the main array instead of them being a nested array.
I have searched but can not find the right solution for this on here, so I am sorry if it turns out to be a duplicate. Then I would like to get the link to the original question.
Upvotes: 1
Views: 4767
Reputation: 541
I have found it!
The solution was to make the array global that I use to store the list items in.
Also I have added $level to the function, so that I can display a specific class style per depth.
And finally the recursive use of the function is not stored in the array as a nested "children array", but gets passed on to the global array that I return in the end.
This gives me exactly the right array:
function category_list($category_parent_id = 0, $level = 0) {
// build our category list only once
static $cats;
global $list_items
if (!is_array($cats)) {
$sql = "SELECT * FROM category";
$result = $db->query($sql);
while ($record = $result->fetch_array()) {
$cats[] = $record;
}
}
foreach ($cats as $cat) {
// if not a match, move on
if ((int) $cat['parent'] !== (int) $category_parent_id) {
continue;
}
$list_items[] = array (
'title' => $cat['title'],
'id' => $cat['cat_id'],
'level'=> $level
);
category_list($cat['cat_id'], $level + 1);
}
return $list_items;
}
Note: Url is not used in this second test, but that is not relevant for the example.
Pfew. Finally.
Upvotes: 3