Laravel 获取祖先(URL)

2021-12-26 00:00:00 php laravel laravel-5 eloquent

在 Laravel 中,我有一个包含 id、parent_id、slug (Self-referring) 的表,

In Laravel, I have a table which contains id, parent_id, slug (Self-referring),

当我有一个ID时,我需要以这样的格式(以/"分隔)获取其所有祖先.

When I have an ID, I need to get all its ancestors in a format like this (Separated by "/").

level1/level2/level3

但是在没有像laravel-nestedset"这样的包的情况下以一种有效的方式".

But in an efficient way without a package like "laravel-nestedset ".

我是这样实现的.

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

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

    $parent = $this->parent;

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

    return $parents;
}

还有其他方法可以有效地做到这一点并用/"分隔吗?

Any other way to do it efficiently and separated by "/" ?

推荐答案

在评论中进行了一些交谈后,我认为这是一个很好的解决方案:

After a little conversation in the comments I think this is a good solution:

// YourModel.php

// Add this line of you want the "parents" property to be populated all the time.
protected $appends = ['parents'];

public function getParentsAttribute()
{
    $collection = collect([]);
    $parent = $this->parent;
    while($parent) {
        $collection->push($parent);
        $parent = $parent->parent;
    }

    return $collection;
}

然后您可以使用以下方法检索您的父母:

Then you can retrieve your parents using:

  • YourModel::find(123)->parents(集合实例)
  • YourModel::find(123)->parents->implode('yourprop', '/')(内爆为字符串,见 https://laravel.com/docs/5.4/collections#method-implode)
  • YourModel::find(123)->parents->reverse()->implode('yourprop', '/')(倒序https://laravel.com/docs/5.4/collections#method-reverse)
  • YourModel::find(123)->parents (collection instance)
  • YourModel::find(123)->parents->implode('yourprop', '/') (imploded to string, see https://laravel.com/docs/5.4/collections#method-implode)
  • YourModel::find(123)->parents->reverse()->implode('yourprop', '/') (reversed order https://laravel.com/docs/5.4/collections#method-reverse)

正如 Nikolai Kiselev https://stackoverflow.com/a/55103589/1346367 所指出的,您也可以将它组合起来这样可以节省一些查询:

As noted by Nikolai Kiselev https://stackoverflow.com/a/55103589/1346367 you may also combine it with this to save a few queries:

protected $with = ['parent.parent.parent'];
// or inline:
YourModel::find(123)->with(['parent.parent.parent']);

这会在对象加载时预加载父级.如果您决定不使用它,则在您调用 $yourModel->parent 时(延迟)加载父项.

This preloads the parent on object load. If you decide not to use this, the parent is (lazy) loaded as soon as you call $yourModel->parent.

相关文章