如何在Laravel中创建嵌套的类别列表?

时间:2017-05-15 22:24:26

标签: php laravel nested-lists

如何在Laravel中创建嵌套的类别列表?

我想创建以下示例:

  • --- Php
  • ------ Laravel
  • ---------版本
  • ------------系列
  • --- Python
  • ------ Django
  • --- Ruby
  • ..........

我的表格字段是:

ID | Name | Parent_id

如果我必须在深度上添加另一列到我的表格,请告诉我。

我正在使用以下代码,但我认为它不是创建嵌套列表类别的最佳解决方案,我不能将此函数传递给我的视图:

function rec($id)
{
     $models = Category::find($id);

     foreach ($models->children as $chield) {
          rec($chield->id);
     }

     return $models->all();
}

function main () {
    $models = Category::whereNull('parent_id')->get();

    foreach ($models as $parent) {
       return rec($parent->id);
    }
}

6 个答案:

答案 0 :(得分:8)

你可以建立一个自我参照模型:

class Category extends Model {

    public function parent()
    {
        return $this->belongsTo('Category', 'parent_id');
    }

    public function children()
    {
        return $this->hasMany('Category', 'parent_id');
    }
}

并建立递归关系:

// recursive, loads all descendants
public function childrenRecursive()
{
   return $this->children()->with('childrenRecursive');
}

让父母带着他们所有的孩子:

$categories = Category::with('childrenRecursive')->whereNull('parent')->get();

最后,您需要遍历子项,直到子项为空。如果你不小心,肯定会遇到一些性能问题。如果这是一个相当小的数据集,您计划保持这种方式,那么它应该不是问题。如果这将成为一个不断增长的列表,那么可以使用root_parent_id或其他东西来查询和手动组装树。

答案 1 :(得分:1)

如果有人需要更好的答案,请查看我的答案,当我遇到这样的问题时,它帮助了我。

   class Category extends Model {

     private $descendants = [];

     public function children()
        {
            return $this->subcategories()->with('children');
        }

     public function hasChildren(){
            if($this->children->count()){
                return true;
            }

            return false;
        }

     public function findDescendants(Category $category){
            $this->descendants[] = $category->id;

            if($category->hasChildren()){
                foreach($category->children as $child){
                    $this->findDescendants($child);
                }
            }
        }

      public function getDescendants(Category $category){
            $this->findDescendants($category);
            return $this->descendants;
        }
 }

在你的控制器中只测试一下:

$category = Category::find(1);
$category_ids = $category->getDescendants($category);

它会在数组中导致id为所有类别的后代,其中id = 1。 然后:

$products = Product::whereIn('category_id',$category_ids)->get();

欢迎您=)

答案 2 :(得分:1)

此函数将返回树数组:

function getCategoryTree($parent_id = 0, $spacing = '', $tree_array = array()) {
    $categories = Category::select('id', 'name', 'parent_id')->where('parent_id' ,'=', $parent_id)->orderBy('parent_id')->get();
    foreach ($categories as $item){
        $tree_array[] = ['categoryId' => $item->id, 'categoryName' =>$spacing . $item->name] ;
        $tree_array = $this->getCategoryTree($item->id, $spacing . '--', $tree_array);
    }
    return $tree_array;
}

答案 3 :(得分:0)

我解决了这个问题:

查看:

    $traverse = function ($categories) use (&$traverse) {
        foreach ($categories as $category) {
            $traverse($cat->Children);
        }
    };
    $traverse(array ($category));

唯一的问题仍然是我无法在控制器中计算信息

<强>型号:

public function Children()
{
    return $this->hasMany($this, 'parent');
}

public function Parent()
{
    return $this->hasOne($this,'id','parent');
}

答案 4 :(得分:0)

我想在这个领域以某种方式搜索某些东西,以获取孩子的深度信息:

    function getDepth($category, $level = 0) {
    if ($category->parent_id>0) {
        if ($category->parent) {
                $level++;
                return $this->getDepth($category->parent, $level);
            }
        }
       return $level;
    }

也许会帮助某人! 干杯!

答案 5 :(得分:0)

您可以这样解决此问题:

class Category extends Model
{
    public function categories()
    {
       return $this->hasMany(Category::class);
    }

    public function childrenCategories()
    {
       return $this->hasMany(Category::class)->with('categories');
    }

}

并获得带有以下子项的类别:

Category::whereNull('category_id')
    ->with('childrenCategories')
    ->get();

注意:只需将parent_id列重命名为category_id