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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With