外键值以数组形式存储时如何单次查询获取关联用户及报表数据?
解决方案
方案1:优雅封装(两次简单查询,写法简洁性能优异)
该方案适配中小数据量场景,两次简单单表查询的开销远低于复杂的JSON关联JOIN,维护成本更低。
- 先给
UserReport模型添加字段类型转换,自动将存储的JSON格式user_id转为PHP数组:
// app/Models/UserReport.php protected $casts = [ 'user_id' => 'array', ];
- 封装关联用户获取访问器,统一调用入口:
// app/Models/UserReport.php public function getUsersAttribute() { return User::whereIn('id', $this->user_id)->get(); }
使用方式非常简洁:
$report = UserReport::find($id); $users = $report->users; // 直接获取关联用户集合
方案2:单次SQL查询(满足单次查询的需求)
基于MySQL原生JSON函数实现关联JOIN,单次查询即可同时拿到报表数据和对应关联用户,需要数据库支持JSON函数(MySQL 5.7+/MariaDB 10.2+及以上版本均支持):
$reportWithUsers = UserReport::select( 'user_report.*', \DB::raw('JSON_ARRAYAGG(JSON_OBJECT( "id", users.id, "name", users.name, "email", users.email )) as users') ) ->leftJoin('users', \DB::raw('JSON_CONTAINS(user_report.user_id, CAST(users.id AS JSON))'), '=', \DB::raw('1')) ->where('user_report.id', $id) ->groupBy('user_report.id') ->first(); // 关联用户数据可直接转为数组使用 $users = json_decode($reportWithUsers->users, true);
优化建议
如果后续业务量持续增长,建议改为规范的多对多关联设计:新增中间表user_report_user存储report_id和user_id的映射关系,使用Laravel默认的belongsToMany关联,查询性能和可维护性都会大幅提升。
内容的提问来源于stack exchange,提问作者Amit Senjaliya
相关产品推荐
相关产品推荐

