简体   繁体   English

Laravel 获取类别的所有父级

[英]Laravel get all parents of category

I have categories and subcategories in laravel我在 laravel 中有类别和子类别

namespace App;

use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    protected $table = 'categories';

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

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

And I can add a new category which belongs to an already created category.我可以添加一个属于已创建类别的新类别。 Something like "Test -> subcategory of test" and then let's say I will create "sub-subcategory of test" which belongs to subcategory of test which will look like this: "Test -> subcategory of test -> sub-subcategory of test" And in the view I want to print the parents of the category if it has any.类似于“测试 -> 测试的子类别”,然后假设我将创建属于测试子类别的“测试的子子类别”,如下所示:“测试 -> 测试的子类别 -> 测试的子子类别" 在视图中,我想打印类别的父项(如果有)。 I do it like this:我这样做:

@if($category->parent)
   <td>{{ $category->parent->name }} <strong>-></strong> {{ $category->name }}</td>
@else
   <td>{{ $category->name }}</td>    
@endif

But this only shows one parent category ("subcategory of test -> sub-subcategori of test").但这仅显示一个父类别(“测试的子类别-> 测试的子子类别”)。 I want to show all the parents which will look like this: "Test->subcategory of test -> sub-subcategory of test" How can I do that?我想向所有父母展示,它们看起来像这样:“测试-> 测试的子类别-> 测试的子子类别”我该怎么做?

You could define a model accessor on Cateory model that retrieves all parents and puts them into a collection.您可以在Cateory模型上定义一个模型访问器,它检索所有父项并将它们放入一个集合中。 So in your Category model add the following method:因此,在您的Category模型中添加以下方法:

public function getParentsAttribute()
{
    $parents = collect([]);

    $parent = $this->parent;

    while(!is_null($parent)) {
        $parents->push($parent);
        $parent = $parent->parent;
    }

    return $parents;
}

then in your blade template you can fetch all the parents of a category然后在您的刀片模板中,您可以获取某个类别的所有父项

@if(count($category->parents))
    <td>{{ $category->parents->implode('-') }} <strong>-></strong> {{ $category->name }}</td>
@else
    <td>{{ $category->name }}</td>
@endif

I see no other solution different from recursively retrieving all the parents and the package suggested by @Ross Wilson in the comments.我认为与递归检索所有父母和@Ross Wilson 在评论中建议的包没有其他解决方案不同。 Take into account that the number of queries will be equal to the number of the parent categories.考虑到查询的数量将等于父类别的数量。

Another thing that you could do is setting the parent tree into the DB in the categories table, to save a lot of queries.您可以做的另一件事是将父树设置到categories表中的数据库中,以节省大量查询。 Add in your categories table a string field like parents_tree and at save/update time set this value with the parent names already concatenated.在您的categories表中添加一个字符串字段,如parents_tree并在保存/更新时将此值设置为已连接的父名称。 This is a little dirty because if one of the parents change its name you have to update all the children accordingly.这有点脏,因为如果其中一个父母更改了它的名字,您必须相应地更新所有孩子。 Is up to you to which trade-off you want to succumb.由您决定要屈服于哪种权衡。

you can append the parent variable:您可以附加父变量:

class Category extends Model
{
    protected $table = 'categories';

    protected $appends = [
        'parent'
    ];

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

It's the shortest solution, but this is not the best way, since then every time a parent object is loaded.这是最短的解决方案,但这不是最好的方法,因为每次加载父对象时都是如此。 Better do this:最好这样做:

class Category extends Model { protected $table = 'categories'; class Category extends Model { protected $table = 'categories';

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

public function getParentsNames() {
    if($this->parent) {
        return $this->parent->getParentsNames(). " > " . $this->name;
    } else {
        return $this->name;
    }
}

In your blade you call: {{ $category->getParentsNames() }}在您的刀片中,您调用: {{ $category->getParentsNames() }}

I know this is old but here is the correct answer for anybody in the future.我知道这是旧的,但这里是未来任何人的正确答案。 This will get you unlimited categories这将为您提供无限的类别

In Category Model在类别模型

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

public function getParentsNames() {

    $parents = collect([]);

    if($this->parent) { 
        $parent = $this->parent;
        while(!is_null($parent)) {
            $parents->push($parent);
            $parent = $parent->parent;
        }
        return $parents;
    } else {
        return $this->name;
    }

}

In Blade (I am sure you can do this on the model level also but here is my fast way of doing it)在 Blade 中(我相信您也可以在模型级别执行此操作,但这是我的快速方法)

 @if ($category->getParentsNames() !== $category->name)
                                @foreach ($category->getParentsNames()->reverse() as $item)
                                    @if ($item->parent_id == 0)
                                        <li class="breadcrumb-item"><a href="/{{ $item->slug }}">{{ $item->name }}</a></li>
                                             @else
                                        <li class="breadcrumb-item"><a href="../{{ $item->slug }}">{{ $item->name }}</a></li>
                                    @endif
                                @endforeach  
                            @endif

Result Home / Living Room / Sofa / Couch Result Home / 客厅 / 沙发 / 沙发

Mine only note to get to the main category, maybe it will be useful to someone.我只注意到进入主要类别,也许它对某人有用。

 static function  getDepth($parent_id) {

       $categories= Categories::find($parent_id);

       if ($categories) {
           if ($categories->parent_id == 0) {
               return $categories->category_name;
           } else {
               return self::getDepth($categories->parent_id);
           }
       }

    }

blade.php刀片.php

   <td>{{ \App\Models\Admin\Category::getDepth($category->parent_id)}}</td>

So far, the best solution I have found is to use a Nested set model .到目前为止,我发现的最佳解决方案是使用Nested set model
Detailed explanation / implementation are quit long and there's already plenty of subject about that.详细的解释/实现已经很长时间了,并且已经有很多关于它的主题。 So I will shorten the subject.所以我将缩短主题。

The idea is to group categories with values that are between parent values and so on.这个想法是用父值之间的值对类别进行分组,依此类推。 Ex:例如:

Clothes : 1-10
    - T-shirts: 2-3
    - Pants: 4-9
        - Shorts 5-6
        - Joggers 7-8

Using theses values, it becomes very easy to query all the ascendants or descendants categories using only one query as they are always contained between two values.使用这些值,只需使用一个查询就可以很容易地查询所有的祖先或后代类别,因为它们总是包含在两个值之间。

One major drawback is;一个主要缺点是; when categories changes (created / deleted / moved), it requires to re-evaluate and update the nodes.当类别发生变化(创建/删除/移动)时,需要重新评估和更新节点。


Here's (IMO) the best explanation I have found: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/这是(IMO)我找到的最好的解释: http : //mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

I have also found this library that seems to works quit nicely https://github.com/lazychaser/laravel-nestedset我还发现这个库似乎可以很好地退出https://github.com/lazychaser/laravel-nestedset

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM