如何展平laravel递归关系集合(树集合)? [英] How do I flatten laravel recursive relationship collection (tree collections)?
问题描述
如何将具有层次结构自引用模型的集合(树集合)展平为一个维集合.我有一个有父母和孩子的自我参照模型.
How do I flatten a collection with hierarchy self referenced models, tree collections into a single dimension collection. I have a self referencing model having parents and children.
我希望结果返回一个雄辩的集合,而不是简单的集合或数组.数组已用作结果结果,便于演示
关系被这样声明.
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()
以使其易于阅读.
so when i call the model->childrenRecursive
it returns the collection as it should be. like this. i have changed it toArray()
to make it easy to read.
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()
的外观.
what I want to achieve is the collection to be single dimension. here is how the toArray()
to that collection should look like.
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"
]
]
我尝试了许多收集方法,例如 filter
, flatMap
, flatten
和多种数组方法.但没有找到合适的解决方案.
I have tried many collection methods like filter
, flatMap
, flatten
and multiple array methods. but haven't found an appropriate solution.
推荐答案
有点晚了,但是我要发布我希望自己能找到的东西,然后再自己写.
It's a bit late, but I'm going to post what I wish I had been able to find before I ended up writing it myself.
类似于原始帖子,我的 categories
表中具有递归的父/子关系(但这可能适用于具有自引用 parent_id
列的任何表).您可以这样设置模型:
Similar to the original post, I have a recursive parent/child relationship in my categories
table (but this could apply to any table with a self-referencing parent_id
column). You can set up your Model like this:
<?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));
}
}
然后,在应用程序中的某个位置,您需要放置一些全局帮助器功能的位置.您可以按照此处找到的说明,然后仅粘贴以下帮助函数:
Then somewhere in your application, you need to have a place to put some global helper functions. You could follow the instructions found here, and then just paste in the following helper functions:
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
将产生所有子类别和子类别的子类别的统一集合,依此类推,直到所有后代类别都被考虑在内.
The code above will then allow you to use $category->flat_ancestors
, which will produce a flat collection of all the category's ancestors, no matter how many there are. Similarly, using $category->flat_descendants
will yield a flat collection of all the child categories, and the child's children categories, and so on until all the posterity categories have been accounted for.
一些需要注意的地方:
- 这种方法可能会导致无限循环,如果您有
类别1
引用类别2
作为其父项,并且那么Category 2
将Category 1
作为其父级.小心一点父母/子女的关系是乱伦的:-) - 这种方法也不是很有效.一堆很好父/子递归关系,尤其是对于
flat_descendants
函数,数据库查询的数量增加每个世代级别都呈指数级增长.
- This type of approach could potentially lead to an infinite loop if
you have
Category 1
referencingCategory 2
as its parent, and thenCategory 2
hasCategory 1
as its parent. Just be careful that parent/child relationships are incest free :-) - This type of approach also isn't very efficient. It'll be fine for a bunch of
parent/child recursive relationships, but especially for the
flat_descendants
functions, the number of database queries grows exponentially for each generation level.
这篇关于如何展平laravel递归关系集合(树集合)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!