在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;
}
任何有效的方法,并用“ /”分隔吗?
答案 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;
}
然后您可以使用以下方法找回父母
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)如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;