Laravel:如何扁平化多维预加载Eloquent集合
扁平化嵌套Eloquent集合(Region模型)
要实现按**父级→子级1→孙级1→孙级2→子级2……**的顺序扁平化嵌套的Region模型集合,且结果保持Eloquent集合类型,可以通过递归遍历的方式实现:
方法一:编写递归处理函数
创建一个辅助函数,递归遍历每个模型及其子级,按顺序收集所有模型:
function flattenRegions($regions) { $flattened = new Illuminate\Database\Eloquent\Collection(); foreach ($regions as $region) { // 添加当前模型到结果集合 $flattened->push($region); // 递归处理预加载的子级关联 if ($region->relationLoaded('descendants') && $region->descendants->isNotEmpty()) { $flattened = $flattened->merge(flattenRegions($region->descendants)); } } return $flattened; } // 使用示例 $originalCollection = // 你的嵌套Region集合 $flattenedCollection = flattenRegions($originalCollection);
方法二:在Region模型中添加实例方法
在Region模型内添加属性方法,直接返回自身及所有子级的扁平化集合:
// app/Models/Region.php public function getFlattenedDescendantsAttribute() { $flattened = new \Illuminate\Database\Eloquent\Collection([$this]); if ($this->relationLoaded('descendants') && $this->descendants->isNotEmpty()) { foreach ($this->descendants as $descendant) { $flattened = $flattened->merge($descendant->flattened_descendants); } } return $flattened; } // 使用示例 // 单个根模型的扁平化 $flattenedFromRoot = $rootRegion->flattened_descendants; // 根集合的扁平化 $flattenedCollection = new \Illuminate\Database\Eloquent\Collection(); $originalCollection->each(function ($region) use (&$flattenedCollection) { $flattenedCollection = $flattenedCollection->merge($region->flattened_descendants); });
关键注意点
- 确保
descendants关联已通过with('descendants')预加载,避免触发N+1查询 - 两种方法返回的都是
Illuminate\Database\Eloquent\Collection实例,保留模型的Eloquent特性 - 遍历顺序严格遵循父级优先、子级深度遍历的要求
内容的提问来源于stack exchange,提问作者Dmitrijs
相关产品推荐
相关产品推荐

