Symfony3.2.6执行DQL查询提示parking_ticket_settings类未定义
问题描述
在Symfony 3.2.6版本框架开发过程中,执行以下代码时抛出未捕获的PHP异常:
$em->persist($AxfonePushPayment); $query = $em->createQuery("SELECT parking_ticket_settings.id FROM parking_ticket_settings JOIN zone z ON(z.id = parking_ticket_settings.zone_id) WHERE z.zone_identifier = '" . $AxfonePushPayment->getZone() . "'"); $ptsID = $query->getResult();
抛出的异常信息如下:
Uncaught PHP Exception Doctrine\ORM\Query\QueryException: "[Semantical Error] line 0, col 39 near 'parking_ticket_settings': Error: Class 'parking_ticket_settings' is not defined." at /var/www/app.clickpark.cz/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php line 63 {"exception":"[object] (Doctrine\\ORM\\Query\\QueryException(code: 0): [Semantical Error] line 0, col 39 near 'parking_ticket_settings': Error: Class 'parking_ticket_settings' is not defined. at /var/www/app.clickpark.cz/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php:63, Doctrine\\ORM\\Query\\QueryException(code: 0): SELECT parking_ticket_settings.id FROM parking_ticket_settings JOIN zone z ON(z.id = parking_ticket_settings.zone_id) WHERE z.zone_identifier = 'BERF' at /var/www/app.clickpark.cz/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php:41)"}
验证说明:上述查询语句直接在MySQL中执行可以正常返回结果。
问题原因
$em->createQuery() 方法接收的是*DQL(Doctrine查询语言)*而非原生SQL,二者语法规则存在本质区别:
- DQL是面向实体对象的查询语言,操作的是项目中定义的Doctrine实体类,不是数据库里的物理表名
- 报错语句直接使用了数据库表名
parking_ticket_settings、zone,Doctrine找不到对应映射的实体类,因此抛出「类未定义」的语义错误 - DQL的联表语法不需要手动写
ON条件,关联关系直接通过实体类上配置的映射字段关联即可
修复方案
- 替换查询中所有的物理表名为对应实体的全限定类名(一般写法是
YourBundleName:EntityName,比如AppBundle:ParkingTicketSettings、AppBundle:Zone),同时给主表设置别名 - 去掉手动写的
ON联表条件,通过实体关联属性完成联表 - 不要直接拼接变量到查询语句里,用参数绑定规避SQL注入风险
修复后的DQL写法参考:
$em->persist($AxfonePushPayment); // 替换为自己项目里实际的实体类命名空间/别名 $query = $em->createQuery("SELECT p.id FROM AppBundle:ParkingTicketSettings p JOIN p.zone z WHERE z.zone_identifier = :zoneId") ->setParameter('zoneId', $AxfonePushPayment->getZone()); $ptsID = $query->getResult();
如果确实需要直接写原生SQL,要换用Doctrine的原生查询接口:
$em->persist($AxfonePushPayment); $sql = "SELECT parking_ticket_settings.id FROM parking_ticket_settings JOIN zone z ON(z.id = parking_ticket_settings.zone_id) WHERE z.zone_identifier = :zoneId"; $query = $em->getConnection()->prepare($sql); $query->execute(['zoneId' => $AxfonePushPayment->getZone()]); $ptsID = $query->fetchAllAssociative();
内容的提问来源于stack exchange,提问作者kuznecov
相关产品推荐
相关产品推荐

