Doctrine Query Builder中FIND_IN_SET无法使用问题求助
解决Doctrine查询simple_array字段包含特定值的问题
嘿,我来帮你搞定这个问题!你遇到的报错主要是因为原生查询(Native Query)的用法有误,以及ResultSetMapping配置不完整,另外也可以用Query Builder更优雅地实现需求,下面分两种方案详细说明:
一、Native Query 正确实现方式
你之前的错误点:
- 原生SQL不能使用
MyBundle:Customer这种Doctrine实体别名,必须用数据库中真实的表名(如果项目配置了表前缀,记得加上前缀,比如app_customer) - 没有正确配置
ResultSetMapping,导致Doctrine无法把查询结果映射为Customer实体 - 你还搞反了
FIND_IN_SET的参数顺序!它的语法是FIND_IN_SET(要搜索的值, 逗号分隔的字符串)
正确代码示例:
// 1. 创建ResultSetMapping,配置实体字段映射 $rsm = new ResultSetMapping(); $rsm->addEntityResult('MyBundle:Customer', 'c'); $rsm->addFieldResult('c', 'id', 'id'); // 映射主键字段 $rsm->addFieldResult('c', 'myNumbers', 'myNumbers'); // 映射目标字段 // 如需其他字段,继续添加addFieldResult即可 // 2. 编写正确的原生SQL $sql = "SELECT c.* FROM Customer c WHERE FIND_IN_SET(:searchNumber, c.myNumbers) > 0"; // 3. 执行查询 $query = $this->entityManager()->createNativeQuery($sql, $rsm); $query->setParameter('searchNumber', $number); $customers = $query->getResult();
二、Query Builder 更优雅的实现
用Query Builder可以避免手写原生SQL的麻烦,这里有两种可靠思路:
方案1:使用MySQL的FIND_IN_SET函数
大多数现代Doctrine版本支持直接调用数据库函数,写法更直观:
$qb = $this->entityManager()->createQueryBuilder(); $customers = $qb->select('c') ->from('MyBundle:Customer', 'c') ->where('FUNCTION(\'FIND_IN_SET\', :searchNumber, c.myNumbers) > 0') ->setParameter('searchNumber', $number) ->getQuery() ->getResult();
方案2:使用LIKE精准匹配(兼容性更强)
如果担心数据库函数兼容性问题,可以用字符串拼接的方式避免误匹配(比如防止199被当成包含99的结果):
$qb = $this->entityManager()->createQueryBuilder(); $customers = $qb->select('c') ->from('MyBundle:Customer', 'c') ->where('CONCAT(\',\', c.myNumbers, \',\') LIKE :searchPattern') ->setParameter('searchPattern', '%,' . $number . ',%') ->getQuery() ->getResult();
总结
- 原生查询必须用真实表名,且配置完整的ResultSetMapping才能映射到实体
- Query Builder的两种方案各有优劣:
FIND_IN_SET更直观,LIKE写法兼容性更强 - 一定要注意
FIND_IN_SET的参数顺序,这是很容易踩的坑!
内容的提问来源于stack exchange,提问作者Zwen2012
相关产品推荐
相关产品推荐

