Laravel中如何用select()获取类似Eloquent的嵌套对象格式结果
Laravel关联查询后返回嵌套对象属性的实现方法
方法一:利用数据库JSON函数直接构造嵌套结构(性能更优)
如果你的数据库支持JSON函数(如MySQL 5.7+、PostgreSQL),可以在select中用DB::raw打包嵌套字段,数据库会直接返回JSON格式结果,Laravel会自动解析为对象/数组:
$results = DB::table('main_table') ->join('related_table', 'main_table.id', '=', 'related_table.main_id') ->select( 'main_table.*', // 将关联表字段打包成嵌套对象 DB::raw('JSON_OBJECT("bar", related_table.some_column) as foo') ) ->get();
返回结果中foo会自动变成{ bar: "some value" }的对象格式,无需额外处理。
方法二:集合手动处理(通用无数据库依赖)
先查询所有需要的字段,再用Laravel集合的map方法构造嵌套结构:
$results = DB::table('main_table') ->join('related_table', 'main_table.id', '=', 'related_table.main_id') ->select( 'main_table.*', 'related_table.some_column as bar' // 先取出需要嵌套的字段 ) ->get() ->map(function ($item) { // 构造嵌套的foo对象 $item->foo = (object)[ 'bar' => $item->bar ]; unset($item->bar); // 不需要原字段可删除 return $item; });
如果要直接修改原集合,用transform替代map即可,用法完全一致。
方法三:大数据量场景用cursor分批处理
如果数据量较大,不想一次性加载所有数据到内存,可用cursor返回生成器逐行处理:
$processedData = []; DB::table('main_table') ->join('related_table', 'main_table.id', '=', 'related_table.main_id') ->select('main_table.*', 'related_table.some_column as bar') ->cursor() ->each(function ($item) use (&$processedData) { $item->foo = (object)['bar' => $item->bar]; unset($item->bar); $processedData[] = $item; });
cursor会逐行读取数据,内存占用远低于get()。
额外:转为Eloquent模型实例
如果需要返回Eloquent模型而非StdClass对象,可通过hydrate方法将处理后的数组转为模型实例:
$models = MainModel::hydrate( DB::table('main_table') ->join('related_table', 'main_table.id', '=', 'related_table.main_id') ->select('main_table.*', 'related_table.some_column as bar') ->get() ->map(function ($item) { $item->foo = (object)['bar' => $item->bar]; unset($item->bar); return (array)$item; }) ->toArray() );
这样得到的$models就是MainModel的集合,拥有模型的所有方法和属性。
内容的提问来源于stack exchange,提问作者Ahmad ElBullock
相关产品推荐
相关产品推荐

