假设我有一个名为categories
的表,例如:
id parent_id title
1 0 food
2 1 drinks
3 2 juice
4 0 furniture
5 3 tables
现在我想在laravel上创建下拉菜单,以便递归显示父类别下的子类别,并使用适当的缩进或-
标记深度。例如:
<select>
<option value="1">food</option>
<option value="2">-drinks</option>
<option value="3">--juice</option>
<option value="4">furniture</option>
<option value="5">-tables</option>
</select>
上面的一个是静态的,但我想动态地生成下拉结构,就像上面的laravel中的categories
表的任何深度的子类别一样递归。
答案 0 :(得分:2)
首先,您可以在控制器上定义 getCategories 方法。递归方法。理想情况下,您应该实现以下内容:
...
// utility method to build the categories tree
private function getCategories($parentId = 0)
{
$categories = [];
foreach(Category::where('parent_id', 0)->get() as $category)
{
$categories = [
'item' => $category,
'children' => $this->getCategories($category->id)
];
}
return $categories;
}
...
之后,您应该将最终的数组/集合(或您选择的任何内容)传递给视图。
return view('my_view', ['categories' => $this->getCategories()])
最后,您可以使用类似于this one的解决方案。
答案 1 :(得分:1)
在get
Eloquent模型上运行Category
方法,或使用查询构建器获取所有类别。
然后编写一个函数并根据需要递归调用它。使用您的类别集合时,filter方法非常有用
这样的事情应该有效:
function getCategories($categories, &$result, $parent_id = 0, $depth = 0)
{
//filter only categories under current "parent"
$cats = $categories->filter(function ($item) use ($parent_id) {
return $item->parent_id == $parent_id;
});
//loop through them
foreach ($cats as $cat)
{
//add category. Don't forget the dashes in front. Use ID as index
$result[$cat->id] = str_repeat('-', $depth) . $cat->title;
//go deeper - let's look for "children" of current category
getCategories($categories, $result, $cat->id, $depth + 1);
}
}
//get categories data. In this case it's eloquent.
$categories = Category::get();
//if you don't have the eloquent model you can use DB query builder:
//$categories = DB::table('categories')->select('id', 'parent_id', 'title')->get();
//prepare an empty array for $id => $formattedVal storing
$result = [];
//start by root categories
getCategories($categories, $result);
我自己没有测试过,但这个想法应该足够明确。好消息是你只执行一个查询。糟糕的是你立刻将整个表加载到内存中。
如果您的表中有更多您不需要此列算法的列,则应在查询中仅指定所需的列。
答案 2 :(得分:1)
不是最优雅,但完成工作:
<?php
$data = [
['id' => 1, 'parent_id' => 0, 'title' => 'food'],
['id' => 2, 'parent_id' => 1, 'title' => 'drinks'],
['id' => 3, 'parent_id' => 2, 'title' => 'juice'],
['id' => 4, 'parent_id' => 0, 'title' => 'furniture'],
['id' => 5, 'parent_id' => 4, 'title' => 'tables']
];
function recursiveElements($data) {
$elements = [];
$tree = [];
foreach ($data as &$element) {
$element['children'] = [];
$id = $element['id'];
$parent_id = $element['parent_id'];
$elements[$id] =& $element;
if (isset($elements[$parent_id])) { $elements[$parent_id]['children'][] =& $element; }
else { $tree[] =& $element; }
}
return $tree;
}
function flattenDown($data, $index=0) {
$elements = [];
foreach($data as $element) {
$elements[] = str_repeat('-', $index) . $element['title'];
if(!empty($element['children'])) $elements = array_merge($elements, flattenDown($element['children'], $index+1));
}
return $elements;
}
$recursiveArray = recursiveElements($data);
$flatten = flattenDown($recursiveArray);
print_r($flatten);
/*
Outputs:
Array
(
[0] => food
[1] => -drinks
[2] => --juice
[3] => furniture
[4] => -tables
)
*/