Using ORM
$timer = new Timer(); //an object marked as a Doctrine Entity
$this->em->persist($timer);
print $timer->getId(); //blank - not yet set
$this->em->flush($timer);
print $timer->getId(); //prints ID of newly inserted record
实际ORM代码(学说)
public function persist($entity)
{
if ( ! is_object($entity)) {
throw ORMInvalidArgumentException::invalidObject('EntityManager#persist()' , $entity);
}
$this->errorIfClosed();
$this->unitOfWork->persist($entity);
}
问题
当上面的ORM代码没有"通过引用"指令时,Doctrine如何将insert_id
插入Entity
?
即通常我会期望这样的事情:
public function persist(&$entity)
{
...
}
以指示在persist
过程中将修改实体(使用 insert_id
)。 但是没有那种东西。 尽管如此,Entity
还是神奇地充满了insert_id
。
这究竟是怎么回事?
对象通过引用传递(和分配)。无需使用运营商地址。
PHP 5 OOP 经常提到的一个关键点是"默认情况下对象通过引用传递"。这并不完全正确。本节通过一些示例来纠正这种一般想法。
PHP 引用是一个别名,它允许两个不同的变量写入相同的值。从 PHP 5 开始,对象变量不再包含对象本身作为值。它只包含一个对象标识符,允许对象访问器查找实际对象。当一个对象通过参数发送、返回或分配给另一个变量时,不同的变量不是别名:它们保存标识符的副本,该标识符指向同一对象。
PHP 文档
在 UnitOfWork::executeInserts 中设置的 Id。
$postInsertIds = $persister->executeInserts();
if ($postInsertIds) {
// Persister returned post-insert IDs
foreach ($postInsertIds as $postInsertId) {
$id = $postInsertId['generatedId'];
$entity = $postInsertId['entity'];
$oid = spl_object_hash($entity);
$idField = $class->identifier[0];
$class->reflFields[$idField]->setValue($entity, $id);