Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Doctrine set private IDs

In PHP, I can create a model with a private/protected $id variable and no setter.

Doctrine ORM is able to set that property when the object is saved/loaded.

How does this work internally? I assume this is handled by serialization, but I haven't been able to find the code responsible of this behavior.

like image 228
Brandon Wamboldt Avatar asked Feb 20 '13 13:02

Brandon Wamboldt


2 Answers

The first time doctrine instantiates an entity (such as a User), it does this:

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

Which creates an object of that type without calling its constructor (deserialization avoids a call to __construct, and they do this intentionally so they don't have to worry about what your constructor looks like or does).

After the first object has been initialized, Doctrine uses clone to make new instances of the same object type.

$entity = clone $this->prototype;

From the cloned objects, it will:

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

The actual code to do this is more complex due to Doctrine's support from compound primary keys, but this should hopefully guide you the right direction.

like image 102
Colin M Avatar answered Nov 13 '22 06:11

Colin M


Doctrine ORM uses reflection to assign identifiers. This is done in the class metadata of your entity.

Un-serialization is only used to create new instances (blueprints) of your entities when the ORM has to instantiate them internally without using constructor params. Once a blueprint is available, it is cloned for each new requested instance.

There's a blogpost on the official website explaining how Doctrine creates new instances of your entities.

like image 30
Ocramius Avatar answered Nov 13 '22 06:11

Ocramius