Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Laravel获取祖先(URL)_Php_Laravel_Laravel 5_Eloquent - Fatal编程技术网

Php Laravel获取祖先(URL)

Php Laravel获取祖先(URL),php,laravel,laravel-5,eloquent,Php,Laravel,Laravel 5,Eloquent,在Laravel中,我有一个包含id、父id、slug(自引用)的表 当我有一个ID时,我需要以如下格式获取它的所有祖先(用“/”分隔) 但在没有像“laravel nestedset”这样的包的情况下,这是一种有效的方式 “ 我是这样实现的 public function parent() { return $this->belongsTo('Collection', 'parent_id'); } public function getParentsAttribute() {

在Laravel中,我有一个包含id、父id、slug(自引用)的表

当我有一个ID时,我需要以如下格式获取它的所有祖先(用“/”分隔)

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

任何其他有效的方法都可以通过“/”

分隔,如果您知道可以嵌套多少个最大级别,那么您可以使用即时加载。假设最大深度为3级,则可以执行以下操作:

$model->with('parent.parent.parent');
您还可以使用递归而不是循环

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

    return collect($this->parent->parents)->push($this->parent);
}
如果要添加第一个对象(self),则完整调用将是:

$model->parents->push($model)->reverse->implode('attr_name', '/');
您还可以将其包装到属性中

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

并像
$model->path那样调用

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

// 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->introde('yourprop','/')
    (introde为string,请参阅)
  • YourModel::find(123)->parents->reverse()->内爆('yourprop','/')
    (顺序相反)
正如Nikolai Kiselev所指出的,您也可以将其与此相结合,以节省一些查询:

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

这将在对象加载时预加载父对象。如果您决定不使用此选项,则只要您调用
$yourModel->parent

,就会加载父级(惰性)。另外,
parents
属性返回一个集合(不过可能是一个普通数组)。然后只需调用
$collection->内爆('/')
就可以将它变成一个字符串。在数据库中是否有一个名为level的列,其中包含level?如果你这样做了,你可以动态构建一个查询来获取所有的父对象,然后使用类似于
GROUP_CONCAT
的方法,让数据库做腿部工作-PS我不使用Laravel,但我使用嵌套集来实现这一点,简单的父子关系会有点困难,因为你需要为每个级别进行连接。有没有办法使用Elount“with()”来实现这一点-渴望加载?@Flame你的意思是像
returncollection::find(33)->parents->introde('/')?哦,很抱歉,当然
父对象
是一个对象,您应该像
->内爆('yourproperty','/')
那样调用它,其中
yourproperty
是父对象的属性。仅当集合只有简单的标量值时,单参数调用才起作用。但这会使调用变得非常困难,因为您的父对象也会嵌套在对象中。您必须使用
$mainObject->parent->parent->parent->parent
访问它们,因此如果您想要一个parents@Flame,没错,但至少不那么重要queries@NikolaiKiselev为什么您认为这个解决方案执行的查询更少?为了检索邻接列表模型中的完整树,我们需要根据树的深度进行连接。(在本例3中)我不确定这是否真的解决了1个查询,即使它解决了,速度的提高是有争议的,因为您正在交易一个PHP循环来从这个嵌套属性创建一个父数组,而原始解决方案是执行3个小查询并在PHP中推送它们array@hoseinz3,每次在
中调用
$parent->parent
,而
getParentsAttribute()
循环将触发一个新的DB查询,除非这些嵌套关系之前已预加载对不起,请再问一个与此相关的问题。有没有办法找到注释者和自我
level1/level2/level3/WITH-THIS
。我想您可以将
$THIS
推送到
getParentsAttribute()
中的$collection中,您可能还需要将
reverse()
方法放在那里。
protected $with = ['parent.parent.parent'];
// or inline:
YourModel::find(123)->with(['parent.parent.parent']);