如何使用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
相关产品推荐
相关产品推荐

