如何在Doctrine QueryBuilder中返回带数组字段的键值结果?
解决QueryBuilder返回分组聚合结果的问题
嘿,我完全懂你想要的效果——把每个学生的科目合并成一个数组,最终只返回2条学生记录对吧?这其实是个很典型的分组聚合需求,咱们来调整你的QueryBuilder代码就能实现:
方法1:用JSON_ARRAYAGG直接生成数组(推荐)
如果你的MySQL版本是5.7及以上,或者用的是MariaDB 10.2+,可以直接用JSON_ARRAYAGG函数,它能帮你把分组后的科目直接拼成JSON数组,不用额外处理:
$this->createQueryBuilder('stud') ->select('stud.name, JSON_ARRAYAGG(s.sub) as sub') ->leftJoin('AppBundle:subject', 's', 'WITH', 's.student = stud.id') ->groupBy('stud.id') // 按学生ID分组,把同一个学生的记录合并 ->getQuery() ->getArrayResult();
这样执行后,John的sub字段会直接是['eng','maths'],Doe的sub则为null,完美符合你的需求。
小提示:如果Doctrine提示找不到
JSON_ARRAYAGG函数,你可能需要在Doctrine的配置里注册一下这个MySQL原生函数,或者确认你的Doctrine版本是2.10及以上(这个版本开始默认支持MySQL的JSON聚合函数)。
方法2:用GROUP_CONCAT配合字符串转数组
如果你的数据库版本不支持JSON函数,可以用GROUP_CONCAT先把科目拼成逗号分隔的字符串,再手动转成数组:
// 先执行查询 $result = $this->createQueryBuilder('stud') ->select('stud.name, GROUP_CONCAT(s.sub) as sub') ->leftJoin('AppBundle:subject', 's', 'WITH', 's.student = stud.id') ->groupBy('stud.id') ->getQuery() ->getArrayResult(); // 把逗号分隔的字符串转成数组 foreach ($result as &$student) { if ($student['sub'] !== null) { $student['sub'] = explode(',', $student['sub']); } } unset($student); // 记得释放引用,避免后续变量污染
这个方法的原理是先把同一个学生的科目用逗号连起来,再通过explode函数拆分成数组。没有科目的学生,GROUP_CONCAT会返回null,不需要额外处理。
关键注意点
一定要用groupBy('stud.id')来分组,因为id是学生表的唯一标识,这样才能保证每个学生只出现在一条结果里。如果只按stud.name分组,万一有同名学生就会出错哦~
内容的提问来源于stack exchange,提问作者Noobie
相关产品推荐
相关产品推荐

