Laravel获取祖先(URL)

时间:2019-03-11 13:49:06

标签: php laravel laravel-5 eloquent

在Laravel中,我有一个表,其中包含id,parent_id,slug(自引用)

当我有一个ID时,我需要以这种格式(由“ /”分隔)获取其所有祖先。

level1/level2/level3

但是没有像“ 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;
}

任何有效的方法,并用“ /”分隔吗?

2 个答案:

答案 0 :(得分:2)

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

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

然后您可以使用以下方法找回父母

如Nikolai Kiselev https://stackoverflow.com/a/55103589/1346367所述,您也可以将其与此结合以保存一些查询:

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

这会在对象加载时预加载父对象。如果您决定不使用此功能,则在您致电$yourModel->parent时,就会(延迟)加载父项。

答案 1 :(得分:0)

如果您知道可以嵌套多少个最大级别,则可以使用“急切加载”。假设最大深度为3个级别,您可以执行以下操作:

$model->with('parent.parent.parent');

您还可以使用递归代替循环。

public function getParentsAttribute()
{
    if (!$this->parent) {
        return collect([]);
    }

    return collect($this->parent->parents)->push($this->parent);
}

如果您也想添加第一个对象(自身),则完整调用为:

$model->parents->push($model)->reverse->implode('attr_name', '/');

您还可以将其包装为属性

public function getPathAttribute() {
    return $model->parents->push($model)->reverse->implode('attr_name', '/');
}

然后像$model->path;

一样拨打电话