Laravel如何将with()关联查询返回的JSON子数组值合并到父级数组
需求实现方案
这个需求完全可以实现,以下是3种不同适用场景的解决方案:
方案1:定义模型访问器(全局生效)
适合所有返回User数据的场景都需要spots直接返回spot_name的情况,修改User模型即可:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class User extends Model { // 已有的其他模型代码... // 定义spots属性访问器 public function getSpotsAttribute() { // 关联为空时返回空字符串避免报错,可根据需求调整默认值 return $this->getRelationValue('spots')?->spot_name ?? ''; } }
如果需要在序列化输出时自动包含该属性,可在模型的$appends属性中添加:
protected $appends = ['spots']; // 如果关联方法名和访问器同名产生冲突,可先修改关联方法的名称,比如把关联方法改为public function spotsRelation(),预加载的时候写with(['spotsRelation:spot_name,spot_uid'])即可
方案2:查询后处理集合(单次生效)
适合仅当前查询需要该结构,不想修改全局模型的情况,直接在查询后通过集合的map方法处理:
$user = User::where('active', 1) ->with(['spots:spot_name,spot_uid']) ->get() ->map(function ($userItem) { $userItem->spots = $userItem->spots?->spot_name ?? ''; return $userItem; });
方案3:使用JOIN直接查询(性能最优)
不需要预加载关联对象,直接通过联表查询把spot_name作为spots字段返回,查询效率更高:
$user = User::where('active', 1) // 无关联spot时也需要返回用户数据请用leftJoin ->leftJoin('spots', 'users.spot_uid', '=', 'spots.spot_uid') // 替换为实际的外键关联字段 ->select('users.*', 'spots.spot_name as spots') ->get();
注意:如果你的
spots是一对多关联(一个用户对应多个spot),可根据需求调整取值逻辑,比如返回所有spot名称的逗号分隔字符串,或者直接返回名称数组即可。
内容的提问来源于stack exchange,提问作者mar fo
相关产品推荐
相关产品推荐

