我如何使用层次结构自引用模型将集合扁平化,将树集合扁平化为单个维度集合。我有一个有父母和孩子的自我参考模型。
我希望结果返回一个有说服力的集合,而不是一个简单的集合或数组。数组已用作结果结果,以便于演示
关系是这样声明的。
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"
]
]
型
我尝试过很多集合方法,比如filter
,flatMap
,flatten
和多个数组方法。但还没有找到合适的解决方案。
6条答案
按热度按时间ee7vknir1#
现在有点晚了,但我将发布我希望在我自己结束写作之前能够找到的东西。
与最初的帖子类似,我在
categories
表中有一个递归的父/子关系(但这可以应用于任何具有自引用parent_id
列的表)。你可以这样设置你的模型:Category.php
字符串
然后在应用程序中的某个地方,您需要有一个地方来放置一些全局帮助器函数。您可以按照instructions found here,然后粘贴以下辅助函数:
Helpers.php
型
上面的代码将允许您使用
$category->flat_ancestors
,这将生成所有类别祖先的平面集合,无论有多少。类似地,使用$category->flat_descendants
将产生所有子类别的平面集合,以及子类别的子类别,依此类推,直到所有后代类别都被考虑在内。注意事项:
Category 1
引用Category 2
作为其父节点,然后Category 2
将Category 1
作为其父节点,则这种方法可能会导致无限循环。只是要小心,父母/孩子的关系是乱伦免费:-)flat_descendants
函数,数据库查询的数量在每个生成级别上都呈指数级增长。monwx1rj2#
我也没有在
Laravel
集合中找到任何内置方法。你可以尝试这样的方法(将其用作全局函数或专用的类方法,这取决于你。这是一个想法):字符串
然后像这样使用它:
型
jutyujz03#
这将递归地变平。但它并不能防止重复,所以如果这是一个问题,你需要过滤掉它们。
在
AppServiceProvider::boot
方法中字符串
然后,
型
rn0zuynd4#
这是我的代码,可能会有帮助。
字符串
您应该将此代码放在AppServiceProvider.php或任何您希望的提供程序的 Boot 方法中,然后您可以像这样使用它
型
这将使树变平并向每个对象添加一个级别属性以指示对象的深度级别
祝大家好运
cxfofazt5#
对于那些因为乱伦关系而陷入死循环的人,我使用这个解决方案通过急切加载的关系来检索后代的属性-工作方式类似于完全扁平化关系,但避免通过
foreach
陷入死循环。Solution link
tez616oj6#
我喜欢这个属性解决方案没有特别的原因,除了能够在获取后使用map轻松提取信息。
字符串