Symfony 5搭配Doctrine时类属性与表字段映射异常问题
问题原因
- 你使用的是DBAL底层原生PDO的
PDO::FETCH_CLASS能力,该功能是PHP原生提供的,完全不识别Doctrine的ORM注解配置,不会自动完成蛇形数据库字段到驼峰实体属性的映射。 - PDO的
FETCH_CLASS默认仅能为类的public属性赋值,你的实体属性均为private权限,PDO没有权限直接写入,所以会在对象上动态创建和数据库字段名同名的public属性,最终出现私有属性全为null、额外新增蛇形公共属性的现象。
解决方案
方案1:使用Doctrine原生查询(最推荐)
你的查询是单表按主键查数据,直接使用Doctrine内置的find方法即可,自动走ORM映射逻辑,无需手动处理字段匹配:
public function getApplicationById(int $id): ?InternApplication { return $this->find($id); }
如果有复杂查询需求,优先使用Doctrine的QueryBuilder或者DQL编写查询,均会自动处理字段映射、私有属性赋值逻辑。
方案2:使用Doctrine原生SQL映射(适用必须写原生SQL的场景)
如果确实需要执行原生SQL,不要直接用PDO的fetch方法,改用Doctrine提供的ResultSetMapping做字段映射:
use Doctrine\ORM\Query\ResultSetMapping; public function getApplicationById(int $id): ?InternApplication { $rsm = new ResultSetMapping(); $rsm->addEntityResult(InternApplication::class, 'ia'); // 配置数据库字段和实体属性的对应关系 $rsm->addFieldResult('ia', 'id', 'id'); $rsm->addFieldResult('ia', 'listing_id', 'listingId'); $rsm->addFieldResult('ia', 'listing_name', 'listingName'); $rsm->addFieldResult('ia', 'listing_emp_mail', 'listingEmployerMail'); $rsm->addFieldResult('ia', 'fname', 'fName'); $rsm->addFieldResult('ia', 'lname', 'lName'); $rsm->addFieldResult('ia', 'email', 'email'); $rsm->addFieldResult('ia', 'phone', 'phone'); $rsm->addFieldResult('ia', 'linkedin_url', 'linkedInUrl'); $rsm->addFieldResult('ia', 'cv_filename', 'cvFilename'); $rsm->addFieldResult('ia', 'status', 'status'); $rsm->addFieldResult('ia', 'created_at', 'createdAt'); $rsm->addFieldResult('ia', 'updated_at', 'updatedAt'); $query = $this->getEntityManager()->createNativeQuery( 'SELECT * FROM intern_applications WHERE id = :id', $rsm ); $query->setParameter('id', $id); return $query->getOneOrNullResult(); }
方案3:兼容原生PDO查询(不推荐)
如果一定要沿用现有原生PDO查询的写法,可以在实体中增加__set方法手动处理蛇形到驼峰的转换和私有属性赋值:
// 写入InternApplication类中 public function __set(string $name, mixed $value): void { // 蛇形命名转驼峰命名 $camelName = lcfirst(str_replace('_', '', ucwords($name, '_'))); if (property_exists($this, $camelName)) { $this->$camelName = $value; } }
该方案会破坏实体的封装性,还会带来额外的性能开销,仅做临时兼容使用,不推荐长期使用。
内容的提问来源于stack exchange,提问作者DebugAndConquer
相关产品推荐
相关产品推荐

