8

在 PHP 中,我可以创建一个带有私有/受保护$id变量且没有设置器的模型。

Doctrine ORM 能够在保存/加载对象时设置该属性。

这在内部如何运作?我假设这是通过序列化处理的,但我无法找到负责此行为的代码。

4

2 回答 2

21

在第一次实例化一个实体(例如 a User)时,它会这样做:

$this->prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));

它在不调用其构造函数的情况下创建了该类型的对象(反序列化避免了对 的调用__construct,并且它们是有意这样做的,因此它们不必担心构造函数的外观或作用)。

在第一个对象被初始化后,Doctrine 使用clone创建相同对象类型的新实例。

$entity = clone $this->prototype;

从克隆的对象中,它将:

$reflection = new \ReflectionObject($entity);
$property = $reflection->getProperty('idField');
$property->setAccessible(true);
$property->setValue($entity, 123);

由于 Doctrine 对复合主键的支持,执行此操作的实际代码更加复杂,但这有望指导您正确的方向。

于 2013-02-20T13:46:57.730 回答
7

Doctrine ORM 使用反射分配标识符。这是在实体的类元数据中完成的。

当 ORM 必须在内部实例化它们而不使用构造函数参数时,反序列化仅用于创建实体的新实例(蓝图)。一旦蓝图可用,就会为每个新请求的实例克隆它。

官方网站上有一篇博文解释了 Doctrine 如何创建实体的新实例。

于 2013-02-20T13:46:36.857 回答