symfony7之getSingleScalarResult方法
getSingleScalarResult() 是 Doctrine 中 Query 对象的方法之一,用于返回查询结果中的单个标量值,比如:
- 一个整数数量(如
COUNT()的结果); - 一个单个字段的值(比如
MAX(price));
✅ 常见用法场景
1. COUNT(...)
$count = $qb
->select('COUNT(o.id)')
->getQuery()
->getSingleScalarResult();
返回的是一个字符串,需要手动强转为 int:
(int) $count
2. SUM(...) / MAX(...) / MIN(...)
$sum = $qb
->select('SUM(o.amount)')
->getQuery()
->getSingleScalarResult(); // 返回 string,例如 '1234.50'
⚠️ 注意事项
返回的是字符串(无论是数字还是其他类型),因此常常需要
(int)或(float)转换;只能用于返回单个结果,否则抛出异常:
Doctrine\ORM\NonUniqueResultException
🚫 不适用的情况:
如果你查询的是多列、多行(比如列表或多字段结构),应使用:
getResult()→ 返回多行多列(数组)getOneOrNullResult()→ 仅用于一个实体对象(或 null)getArrayResult()→ 返回数组结构
symfony7对于 getSingleResult 的使用
在 Symfony 7(Doctrine ORM)中,
getSingleResult()仍然会生效,即使执行的是一个SELECT COUNT(...),SUM(...)这样的聚合查询,并返回多列别名字段。
来看一下这段代码:
->select(
'COUNT(p.id) as total',
"SUM(CASE WHEN p.status = :accepted THEN 1 ELSE 0 END) as accepted",
"SUM(CASE WHEN p.status = :rejected THEN 1 ELSE 0 END) as rejected"
)
这是一个只会返回一行结果的聚合查询(没有 GROUP BY), 调用:
$qb->getQuery()->getSingleResult();
它将返回一个关联数组(如果你使用的是 Query::HYDRATE_ARRAY 或默认的 hydrate mode):
[
'total' => '10',
'accepted' => '5',
'rejected' => '1'
]
注意返回值中的数字是字符串形式(因为 SQL 查询返回的是字符串类型),所以你用:
return array_map('intval', $qb->getQuery()->getSingleResult());
是正确且常见的做法 —— 把这些聚合数值字段全部转为 int 类型。
array_map('intval', $array) 会对数组中 每一个值 执行 intval() 转换操作,无论键名是什么(键名会保留)。
例如:
$data = [
'total' => '10',
'accepted' => '5',
'rejected' => '1'
];
$result = array_map('intval', $data);
执行后 $result 为:
[
'total' => 10,
'accepted' => 5,
'rejected' => 1
]
✅ 总结:
- ✅ 会转换每个 值 为整数。
- ✅ 键名不变。
- ❌ 不会处理嵌套数组(只是浅层转换)。
如果你只想转换某些字段,可以单独写:
$result = $qb->getQuery()->getSingleResult();
$result['total'] = (int) $result['total'];
补充说明:
如果用的是 DQL(Doctrine Query Language):
getSingleResult() 会返回一个索引数组或对象,取决于你的 DQL 查询和 hydration 方式。
如果你想确保返回关联数组:
你可以显示设置 hydration mode 为 HYDRATE_ARRAY:
return array_map('intval', $qb->getQuery()->getSingleResult(\Doctrine\ORM\Query::HYDRATE_ARRAY));
但在使用 QueryBuilder 默认是 HYDRATE_ARRAY,你写法就已经 OK。
✅ 结论:
getSingleResult()在你的这个 SQL 聚合查询中是生效的,会返回一行数组,array_map('intval', ...)用于转整型也完全合理。可以放心使用。- 适用于单行数据,而无论是单个字段还是多个字段
