递归显示laravel中的下拉列表

时间:2015-09-07 19:27:56

标签: php laravel laravel-5

假设我有一个名为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表的任何深度的子类别一样递归。

3 个答案:

答案 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
)
 */