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

如何使用Laravel Collection将对象数组转换为嵌套对象

优雅实现Laravel中对象数组转嵌套对象的几种方案

Hey there! 在Laravel里把从SQL查出来的扁平对象数组转成嵌套结构,确实有不少优雅的玩法,咱先分两种常见场景来说哈,你可以根据自己的数据结构选合适的:

场景1:简单一对多嵌套(比如分类下的文章、用户下的订单)

假设你从SQL拿到的是类似这样的扁平对象数组:

// 示例数据:分类+关联文章的扁平结果
$flatItems = [
    (object) ['category_id' => 1, 'category_name' => '技术专栏', 'post_id' => 1, 'post_title' => 'Laravel集合进阶技巧'],
    (object) ['category_id' => 1, 'category_name' => '技术专栏', 'post_id' => 2, 'post_title' => 'Eloquent性能优化'],
    (object) ['category_id' => 2, 'category_name' => '生活日常', 'post_id' => 3, 'post_title' => '手冲咖啡指南'],
];

用Laravel集合的groupBy+map组合就能轻松搞定,代码可读性拉满:

$nestedData = collect($flatItems)
    // 先按分类ID分组
    ->groupBy('category_id')
    // 处理每个分组,组装成嵌套结构
    ->map(function ($group) {
        // 取分组里第一个对象的分类信息(因为同组分类信息一致)
        $category = $group->first();
        return (object) [
            'category_id' => $category->category_id,
            'category_name' => $category->category_name,
            // 把分组里的文章提取出来,作为子数组
            'posts' => $group->map(function ($item) {
                return (object) [
                    'post_id' => $item->post_id,
                    'post_title' => $item->post_title,
                ];
            })->values()->all()
        ];
    })
    // 重置索引,去掉category_id作为键名
    ->values()
    // 转成普通对象数组(如果需要的话)
    ->all();

场景2:无限级层级结构(比如无限分类、评论楼)

如果你的数据是有父级关联的层级结构(比如每个分类有parent_id),示例数据:

$flatCategories = [
    (object) ['id' => 1, 'name' => '技术', 'parent_id' => 0],
    (object) ['id' => 2, 'name' => '前端开发', 'parent_id' => 1],
    (object) ['id' => 3, 'name' => 'Vue.js', 'parent_id' => 2],
    (object) ['id' => 4, 'name' => '生活', 'parent_id' => 0],
];

可以写一个递归函数结合集合来处理,逻辑清晰且支持无限层级:

/**
 * 构建嵌套层级结构
 * @param array $items 扁平对象数组
 * @param int $parentId 父级ID,默认根节点
 * @return array 嵌套对象数组
 */
function buildNestedStructure($items, $parentId = 0) {
    return collect($items)
        // 筛选当前父级下的子项
        ->where('parent_id', $parentId)
        // 给每个子项添加children属性,递归处理子级
        ->map(function ($item) use ($items) {
            $item->children = buildNestedStructure($items, $item->id);
            return $item;
        })
        // 重置索引
        ->values()
        ->all();
}

// 使用示例
$nestedCategories = buildNestedStructure($flatCategories);

最优解:如果用Eloquent查询,直接用关联预加载!

如果你是通过Eloquent模型查询的数据,那完全不用手动组装——直接用**关联预加载(with)**就可以自动得到嵌套结构,这是Laravel最推荐的优雅方式:

// 先在Category模型里定义关联关系
class Category extends Model
{
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

// 查询时直接预加载关联
$nestedData = Category::with('posts')->get();

这样返回的每个Category对象都会自动带上posts属性,里面就是对应的Post对象数组,完全省去手动组装的麻烦!


内容的提问来源于stack exchange,提问作者Dayo Choul

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:58:34