You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Laravel从同表获取含子行的数据并整合到同一集合

问题描述

我有一张包含父行和子行的表,需要使用Laravel将数据获取到同一集合中,即把子行数据嵌套在对应的父行内。表结构如下:

idtypepriceis_substitutesubsitute_parent
1Type A120null
2Type B4411
3Type C2311
4Type D110null
5Type E4514
6Type F2514

其中subsitute_parent字段表示该行对应的父行ID。我尝试过先获取全表数据,再通过foreach拆分父行和子行,但这种方法效率较低,代码如下:

$returnedData = ItemModel::all();
$structPODetails = [];

foreach ($returnedData as  $tableRow) {
    if (!empty($tableRow->subsitute_parent)) {
       $structPODetails['child_items'][] = $tableRow;
    } else {
       $structPODetails['parent_items'][] = $tableRow;
    }
}

return $structPODetails;

请问如何用Laravel高效实现将子行数据嵌套到对应父行的需求?

解决方案

1. 定义模型关联

在ItemModel中添加关联方法,用来绑定父项与子项的关系:

class ItemModel extends Model
{
    // 关联当前父项的所有子替代项
    public function substitutes()
    {
        return $this->hasMany(ItemModel::class, 'subsitute_parent', 'id');
    }
}

参数说明:依次为关联模型类名、子表外键字段名、父表关联主键字段名。

2. 预加载关联数据(避免N+1查询)

使用Laravel的预加载功能,只需要2次SQL查询就能完成所有父项与对应子项的关联,效率远高于手动循环匹配:

// 获取所有父项(is_substitute=0)并自动嵌套对应的子项
$parentItems = ItemModel::where('is_substitute', 0)
    ->with('substitutes')
    ->get();

return $parentItems;

返回的集合中,每个父项对象都会包含substitutes属性,该属性就是对应父行的所有子行数据,完全符合嵌套需求。

3. 可选:处理全量数据的嵌套场景

如果需要保留所有数据并完成嵌套,可借助集合方法处理,但仍优先推荐上面的预加载方式(数据量大时更高效):

$allItems = ItemModel::all();

// 按subsitute_parent分组,null对应父项
$groupedItems = $allItems->groupBy('subsitute_parent');

// 为父项绑定对应的子项
$structuredItems = $groupedItems->get(null)->map(function ($parent) use ($groupedItems) {
    $parent->substitutes = $groupedItems->get($parent->id) ?? collect();
    return $parent;
});

return $structuredItems;

效率对比

原方法仅完成了父项与子项的拆分,未实现嵌套,若手动完成嵌套还需额外循环匹配,会增加内存消耗与代码复杂度。而Laravel的关联预加载利用数据库的关联查询能力,一次性完成数据映射,查询次数更少,代码更简洁。

内容的提问来源于stack exchange,提问作者Shasika Madhushan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 08:01:00