How does Doctrine set private IDs

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.