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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43989728/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 15:58:09  来源:igfitidea点击:

How to create a nested-list of categories in Laravel?

phplaravelnested-lists

提问by X 47 48 - IR

How can I create a nested list of categories in Laravel?

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

I want to create something like this:

我想创建这样的东西:

  • --- Php
  • ------ Laravel
  • --------- Version
  • ------------ V 5.7
  • --- Python
  • ------ Django
  • --- Ruby
  • ..........
  • --- PHP
  • ------ Laravel
  • - - - - - 版本
  • ------------ V 5.7
  • ---蟒蛇
  • ------ 姜戈
  • ---红宝石
  • .....

The fields of my categories table are:

我的类别表的字段是:

id | name | parent_id

If I have to add another column like depth or something, please tell me.

如果我必须添加另一列,如深度或其他内容,请告诉我。

I am using this following code, but I think it is not the best solution. Besides, I can not pass this function to my view.

我正在使用以下代码,但我认为这不是最佳解决方案。此外,我无法将此功能传递给我的视图。

function rec($id)
{
     $model = Category::find($id);
     foreach ($model->children as $chield) rec($chield->id);
     return $model->all();
}

function main () {
    $models = Category::whereNull('parent_id')->get();
    foreach ($models as $parent) return rec($parent->id);
}

回答by Alex Harris

You can make a self-referential model:

您可以制作一个自我参考模型:

class Category extends Model {

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

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

and make a recursive relation:

并建立递归关系:

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

and to get parents with all their children:

并让父母和他们所有的孩子:

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

Lastly you need to just iterate through the children until children is null. There can definitely be some performance issues with this if you are not careful. If this is a fairly small dataset that you plan to remain that way it shouldn't be an issue. If this is going to be an ever growing list it might make sense to have a root_parent_idor something to query off of and assemble the tree manually.

最后,您只需要遍历孩子,直到孩子为空。如果您不小心,肯定会出现一些性能问题。如果这是一个相当小的数据集,您打算保持这种方式,那么这应该不是问题。如果这将是一个不断增长的列表,那么root_parent_id手动查询和组装树可能是有意义的。

回答by tokkerbaz

If someone needs a better answer look up my answer, it helped me, when I had faced with such a problem.

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

   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;
        }
 }

And In your Controller just test this:

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

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

It will result ids in array all descendants of your category where id=1. then :

它将导致 ids 在您的类别的所有后代中,其中 id=1。然后 :

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

You are welcome =)

不客气=)

回答by nickRO87

Searching for something somehow in this area I wanted to share a functionality for getting the depth level of child:

在这方面以某种方式搜索某些东西,我想分享一个获取孩子深度级别的功能:

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

Maybe it will help someone! Cheers!

也许它会帮助某人!干杯!

回答by Amir Kaftari

you can solve this problem like this :

你可以这样解决这个问题:

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

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

}

and get category with children like this :

并像这样获得孩子的类别:

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

notice : just rename parent_id column to category_id

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

回答by X 47 48 - IR

This also worked:

这也有效:

View:

看法:

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

Model:

模型:

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

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