Skip to content

Commit

Permalink
Merge pull request #10743 from mpdude/post-insert-id-early
Browse files Browse the repository at this point in the history
Make EntityPersisters tell the UoW about post insert IDs early
  • Loading branch information
greg0ire authored Jun 25, 2023
2 parents 70bcff7 + 8bc74c6 commit 7ef4afc
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 85 deletions.
6 changes: 6 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Upgrade to 2.16

## Deprecated returning post insert IDs from `EntityPersister::executeInserts()`

Persisters implementing `\Doctrine\ORM\Persisters\Entity\EntityPersister` should no longer
return an array of post insert IDs from their `::executeInserts()` method. Make the
persister call `Doctrine\ORM\UnitOfWork::assignPostInsertId()` instead.

## Changing the way how reflection-based mapping drivers report fields, deprecated the "old" mode

In ORM 3.0, a change will be made regarding how the `AttributeDriver` reports field mappings.
Expand Down
16 changes: 6 additions & 10 deletions lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,10 @@ public function getInserts()
public function executeInserts()
{
if (! $this->queuedInserts) {
return [];
return;
}

$postInsertIds = [];
$uow = $this->em->getUnitOfWork();
$idGenerator = $this->class->idGenerator;
$isPostInsertId = $idGenerator->isPostInsertGenerator();

Expand All @@ -280,12 +280,10 @@ public function executeInserts()
$stmt->executeStatement();

if ($isPostInsertId) {
$generatedId = $idGenerator->generateId($this->em, $entity);
$id = [$this->class->identifier[0] => $generatedId];
$postInsertIds[] = [
'generatedId' => $generatedId,
'entity' => $entity,
];
$generatedId = $idGenerator->generateId($this->em, $entity);
$id = [$this->class->identifier[0] => $generatedId];

$uow->assignPostInsertId($entity, $generatedId);
} else {
$id = $this->class->getIdentifierValues($entity);
}
Expand All @@ -296,8 +294,6 @@ public function executeInserts()
}

$this->queuedInserts = [];

return $postInsertIds;
}

/**
Expand Down
10 changes: 4 additions & 6 deletions lib/Doctrine/ORM/Persisters/Entity/EntityPersister.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,17 +109,15 @@ public function getSelectConditionStatementSQL($field, $value, $assoc = null, $c
public function addInsert($entity);

/**
* Executes all queued entity insertions and returns any generated post-insert
* identifiers that were created as a result of the insertions.
* Executes all queued entity insertions.
*
* If no inserts are queued, invoking this method is a NOOP.
*
* @psalm-return list<array{
* @psalm-return void|list<array{
* generatedId: int,
* entity: object
* }> An array of any generated post-insert IDs. This will be
* an empty array if the entity class does not use the
* IDENTITY generation strategy.
* }> Returning an array of generated post-insert IDs is deprecated, implementations
* should call UnitOfWork::assignPostInsertId() and return void.
*/
public function executeInserts();

Expand Down
16 changes: 6 additions & 10 deletions lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ public function getOwningTable($fieldName)
public function executeInserts()
{
if (! $this->queuedInserts) {
return [];
return;
}

$postInsertIds = [];
$uow = $this->em->getUnitOfWork();
$idGenerator = $this->class->idGenerator;
$isPostInsertId = $idGenerator->isPostInsertGenerator();
$rootClass = $this->class->name !== $this->class->rootEntityName
Expand Down Expand Up @@ -157,12 +157,10 @@ public function executeInserts()
$rootTableStmt->executeStatement();

if ($isPostInsertId) {
$generatedId = $idGenerator->generateId($this->em, $entity);
$id = [$this->class->identifier[0] => $generatedId];
$postInsertIds[] = [
'generatedId' => $generatedId,
'entity' => $entity,
];
$generatedId = $idGenerator->generateId($this->em, $entity);
$id = [$this->class->identifier[0] => $generatedId];

$uow->assignPostInsertId($entity, $generatedId);
} else {
$id = $this->em->getUnitOfWork()->getEntityIdentifier($entity);
}
Expand Down Expand Up @@ -194,8 +192,6 @@ public function executeInserts()
}

$this->queuedInserts = [];

return $postInsertIds;
}

/**
Expand Down
62 changes: 41 additions & 21 deletions lib/Doctrine/ORM/UnitOfWork.php
Original file line number Diff line number Diff line change
Expand Up @@ -1171,30 +1171,24 @@ private function executeInserts(ClassMetadata $class): void

$postInsertIds = $persister->executeInserts();

if ($postInsertIds) {
if (is_array($postInsertIds)) {
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/pull/10743/',
'Returning post insert IDs from \Doctrine\ORM\Persisters\Entity\EntityPersister::executeInserts() is deprecated and will not be supported in Doctrine ORM 3.0. Make the persister call Doctrine\ORM\UnitOfWork::assignPostInsertId() instead.'
);

// Persister returned post-insert IDs
foreach ($postInsertIds as $postInsertId) {
$idField = $class->getSingleIdentifierFieldName();
$idValue = $this->convertSingleFieldIdentifierToPHPValue($class, $postInsertId['generatedId']);

$entity = $postInsertId['entity'];
$oid = spl_object_id($entity);

$class->reflFields[$idField]->setValue($entity, $idValue);

$this->entityIdentifiers[$oid] = [$idField => $idValue];
$this->entityStates[$oid] = self::STATE_MANAGED;
$this->originalEntityData[$oid][$idField] = $idValue;

$this->addToIdentityMap($entity);
$this->assignPostInsertId($postInsertId['entity'], $postInsertId['generatedId']);
}
} else {
foreach ($insertionsForClass as $oid => $entity) {
if (! isset($this->entityIdentifiers[$oid])) {
//entity was not added to identity map because some identifiers are foreign keys to new entities.
//add it now
$this->addToEntityIdentifiersAndEntityMap($class, $oid, $entity);
}
}

foreach ($insertionsForClass as $oid => $entity) {
if (! isset($this->entityIdentifiers[$oid])) {
//entity was not added to identity map because some identifiers are foreign keys to new entities.
//add it now
$this->addToEntityIdentifiersAndEntityMap($class, $oid, $entity);
}
}

Expand Down Expand Up @@ -3819,4 +3813,30 @@ private function normalizeIdentifier(ClassMetadata $targetClass, array $flatIden

return $normalizedAssociatedId;
}

/**
* Assign a post-insert generated ID to an entity
*
* This is used by EntityPersisters after they inserted entities into the database.
* It will place the assigned ID values in the entity's fields and start tracking
* the entity in the identity map.
*
* @param object $entity
* @param mixed $generatedId
*/
final public function assignPostInsertId($entity, $generatedId): void
{
$class = $this->em->getClassMetadata(get_class($entity));
$idField = $class->getSingleIdentifierFieldName();
$idValue = $this->convertSingleFieldIdentifierToPHPValue($class, $generatedId);
$oid = spl_object_id($entity);

$class->reflFields[$idField]->setValue($entity, $idValue);

$this->entityIdentifiers[$oid] = [$idField => $idValue];
$this->entityStates[$oid] = self::STATE_MANAGED;
$this->originalEntityData[$oid][$idField] = $idValue;

$this->addToIdentityMap($entity);
}
}

This file was deleted.

0 comments on commit 7ef4afc

Please sign in to comment.