Dennis
Dennis

Reputation: 8111

How does Doctrine populate id property of an Entity after successful insert/persist operation?

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

Actual ORM Code (Doctrine)

public function persist($entity)
{
    if ( ! is_object($entity)) {
        throw ORMInvalidArgumentException::invalidObject('EntityManager#persist()' , $entity);
    }

    $this->errorIfClosed();

    $this->unitOfWork->persist($entity);
}

Question

How does Doctrine insert insert_id into the Entity, when the ORM's code above has no "pass by reference" directive?

I.e. normally I'd expect something like this:

public function persist(&$entity)
{
    ...
}

to indicate that the entity will be modified (with insert_id) during the persist process. But there is nothing of the sort. Nevertheless, Entity is populated with insert_id magically.

How does that happen exactly?

Upvotes: 2

Views: 915

Answers (1)

d.garanzha
d.garanzha

Reputation: 813

Objects are passed (and assigned) by reference. No need to use address of operator.

One of the key-points of PHP 5 OOP that is often mentioned is that "objects are passed by references by default". This is not completely true. This section rectifies that general thought using some examples.

A PHP reference is an alias, which allows two different variables to write to the same value. As of PHP 5, an object variable doesn't contain the object itself as value anymore. It only contains an object identifier which allows object accessors to find the actual object. When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.

PHP documentation

Id set in UnitOfWork::executeInserts.

$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);

Upvotes: 1

Related Questions