gpt4 book ai didi

php - 如何展平 laravel 递归关系集合(树集合)?

转载 作者:可可西里 更新时间:2023-11-01 01:15:03 25 4
gpt4 key购买 nike

如何将具有层次结构自引用模型的集合、树集合展平为单一维度集合。我有一个包含 parent 和 child 的自引用模型。

我希望结果返回一个 Eloquent 集合,而不是一个简单的集合或数组。 array已被用作result结果,方便演示

关系是这样声明的。

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

public function parentRecursive()
{
return $this->parent()->with('parentRecursive');
}

public function children()
{
return $this->hasMany(self::class, 'parent_id');
}

public function childrenRecursive()
{
return $this->children()->with('childrenRecursive');
}

所以当我调用 model->childrenRecursive 时,它会按原样返回集合。像这样。我已将其更改为 toArray() 以使其易于阅读。

array:1 [
0 => array:6 [
"id" => 5
"name" => "I am a child of 1"
"parent_id" => "1"
"created_at" => "2016-12-26 13:53:50"
"updated_at" => "2016-12-26 13:53:50"
"children_recursive" => array:1 [
0 => array:6 [
"id" => 6
"name" => "I am child of 5"
"parent_id" => "5"
"created_at" => "2016-12-26 13:53:50"
"updated_at" => "2016-12-26 13:53:50"
"children_recursive" => array:2 [
0 => array:6 [
"id" => 7
"name" => "I am child of 6"
"parent_id" => "6"
"created_at" => "2016-12-26 13:53:50"
"updated_at" => "2016-12-26 13:53:50"
"children_recursive" => []
],
1 => array:6 [
"id" => 8
"name" => "I am child of 6 too"
"parent_id" => "6"
"created_at" => "2016-12-26 13:53:50"
"updated_at" => "2016-12-26 13:53:50"
"children_recursive" => []
]
]
]
]
]
]

我想要实现的是集合是单一维度的。这是该集合的 toArray() 的样子。

array:4 [
0 => array:6 [
"id" => 5
"name" => "I am a child of 1"
"parent_id" => "1"
"created_at" => "2016-12-26 13:53:50"
"updated_at" => "2016-12-26 13:53:50"
],
1 => array:6 [
"id" => 6
"name" => "I am child of 5"
"parent_id" => "5"
"created_at" => "2016-12-26 13:53:50"
"updated_at" => "2016-12-26 13:53:50"
],
2 => array:6 [
"id" => 7
"name" => "I am child of 6"
"parent_id" => "6"
"created_at" => "2016-12-26 13:53:50"
"updated_at" => "2016-12-26 13:53:50"
],
3 => array:6 [
"id" => 8
"name" => "I am child of 6 too"
"parent_id" => "6"
"created_at" => "2016-12-26 13:53:50"
"updated_at" => "2016-12-26 13:53:50"
]
]

我尝试过很多收集方法,比如filterflatMapflatten和多种数组方法。但还没有找到合适的解决方案。

最佳答案

有点晚了,但我要发布我希望在我自己写完之前能够找到的东西。

与原始帖子类似,我的 categories 表中有一个递归的父/子关系(但这可能适用于任何具有自引用 parent_id 列的表).您可以像这样设置您的模型:

分类.php

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class Category extends Model {

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

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

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

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

// Attributes
public function getFlatAncestorsAttribute()
{
return collect(flat_ancestors($this));
}

public function getFlatDescendantsAttribute()
{
return collect(flat_descendants($this));
}
}

然后在你的应用程序的某个地方,你需要有一个地方来放置一些全局辅助函数。可以关注instructions found here ,然后粘贴以下辅助函数:

Helpers.php

function flat_ancestors($model) {
$result = [];
if ($model->parent) {
$result[] = $model->parent;
$result = array_merge($result, flat_ancestors($model->parent));
}
return $result;
}

function flat_descendants($model) {
$result = [];
foreach ($model->children as $child) {
$result[] = $child;
if ($child->children) {
$result = array_merge($result, flat_descendants($child));
}
}
return $result;
}

然后上面的代码将允许您使用 $category->flat_ancestors,这将生成所有类别祖先的平面集合,无论有多少。类似地,使用 $category->flat_descendants 将生成所有子类别的平面集合,以及子类别的子类别,依此类推,直到所有后代类别都被考虑在内。

注意事项:

  • 这种方法可能会导致无限循环,如果您有 Category 1 引用 Category 2 作为其父项,并且然后 Category 2Category 1 作为其父级。只是要小心 parent /子女的关系是无乱伦的:-)
  • 这种方法也不是很有效。对一群人来说没问题父/子递归关系,但特别是对于flat_descendants 函数,数据库查询数量增长每个世代水平呈指数增长。

关于php - 如何展平 laravel 递归关系集合(树集合)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41334131/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com