Skip to content

Commit 8bc74c6

Browse files
committed
Make EntityPersisters tell the UoW about post insert IDs early
This refactoring does two things: * We can avoid collecting the post insert IDs in a cumbersome array structure that will be returned by the EntityPersisters and processed by the UoW right after. Instead, use a more expressive API: Make the EntityPersisters tell the UoW about the IDs immediately. * IDs will be available in inserted entities a tad sooner. That may help to resolve doctrine#10735, where we can use the IDs to skip extra updates.
1 parent 41f704c commit 8bc74c6

File tree

6 files changed

+63
-85
lines changed

6 files changed

+63
-85
lines changed

UPGRADE.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Upgrade to 2.16
22

3+
## Deprecated returning post insert IDs from `EntityPersister::executeInserts()`
4+
5+
Persisters implementing `\Doctrine\ORM\Persisters\Entity\EntityPersister` should no longer
6+
return an array of post insert IDs from their `::executeInserts()` method. Make the
7+
persister call `Doctrine\ORM\UnitOfWork::assignPostInsertId()` instead.
8+
39
## Changing the way how reflection-based mapping drivers report fields, deprecated the "old" mode
410

511
In ORM 3.0, a change will be made regarding how the `AttributeDriver` reports field mappings.

lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php

+6-10
Original file line numberDiff line numberDiff line change
@@ -256,10 +256,10 @@ public function getInserts()
256256
public function executeInserts()
257257
{
258258
if (! $this->queuedInserts) {
259-
return [];
259+
return;
260260
}
261261

262-
$postInsertIds = [];
262+
$uow = $this->em->getUnitOfWork();
263263
$idGenerator = $this->class->idGenerator;
264264
$isPostInsertId = $idGenerator->isPostInsertGenerator();
265265

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

282282
if ($isPostInsertId) {
283-
$generatedId = $idGenerator->generateId($this->em, $entity);
284-
$id = [$this->class->identifier[0] => $generatedId];
285-
$postInsertIds[] = [
286-
'generatedId' => $generatedId,
287-
'entity' => $entity,
288-
];
283+
$generatedId = $idGenerator->generateId($this->em, $entity);
284+
$id = [$this->class->identifier[0] => $generatedId];
285+
286+
$uow->assignPostInsertId($entity, $generatedId);
289287
} else {
290288
$id = $this->class->getIdentifierValues($entity);
291289
}
@@ -296,8 +294,6 @@ public function executeInserts()
296294
}
297295

298296
$this->queuedInserts = [];
299-
300-
return $postInsertIds;
301297
}
302298

303299
/**

lib/Doctrine/ORM/Persisters/Entity/EntityPersister.php

+4-6
Original file line numberDiff line numberDiff line change
@@ -109,17 +109,15 @@ public function getSelectConditionStatementSQL($field, $value, $assoc = null, $c
109109
public function addInsert($entity);
110110

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

lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php

+6-10
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,10 @@ public function getOwningTable($fieldName)
109109
public function executeInserts()
110110
{
111111
if (! $this->queuedInserts) {
112-
return [];
112+
return;
113113
}
114114

115-
$postInsertIds = [];
115+
$uow = $this->em->getUnitOfWork();
116116
$idGenerator = $this->class->idGenerator;
117117
$isPostInsertId = $idGenerator->isPostInsertGenerator();
118118
$rootClass = $this->class->name !== $this->class->rootEntityName
@@ -157,12 +157,10 @@ public function executeInserts()
157157
$rootTableStmt->executeStatement();
158158

159159
if ($isPostInsertId) {
160-
$generatedId = $idGenerator->generateId($this->em, $entity);
161-
$id = [$this->class->identifier[0] => $generatedId];
162-
$postInsertIds[] = [
163-
'generatedId' => $generatedId,
164-
'entity' => $entity,
165-
];
160+
$generatedId = $idGenerator->generateId($this->em, $entity);
161+
$id = [$this->class->identifier[0] => $generatedId];
162+
163+
$uow->assignPostInsertId($entity, $generatedId);
166164
} else {
167165
$id = $this->em->getUnitOfWork()->getEntityIdentifier($entity);
168166
}
@@ -194,8 +192,6 @@ public function executeInserts()
194192
}
195193

196194
$this->queuedInserts = [];
197-
198-
return $postInsertIds;
199195
}
200196

201197
/**

lib/Doctrine/ORM/UnitOfWork.php

+41-21
Original file line numberDiff line numberDiff line change
@@ -1143,30 +1143,24 @@ private function executeInserts(ClassMetadata $class): void
11431143

11441144
$postInsertIds = $persister->executeInserts();
11451145

1146-
if ($postInsertIds) {
1146+
if (is_array($postInsertIds)) {
1147+
Deprecation::trigger(
1148+
'doctrine/orm',
1149+
'https://github.com/doctrine/orm/pull/10743/',
1150+
'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.'
1151+
);
1152+
11471153
// Persister returned post-insert IDs
11481154
foreach ($postInsertIds as $postInsertId) {
1149-
$idField = $class->getSingleIdentifierFieldName();
1150-
$idValue = $this->convertSingleFieldIdentifierToPHPValue($class, $postInsertId['generatedId']);
1151-
1152-
$entity = $postInsertId['entity'];
1153-
$oid = spl_object_id($entity);
1154-
1155-
$class->reflFields[$idField]->setValue($entity, $idValue);
1156-
1157-
$this->entityIdentifiers[$oid] = [$idField => $idValue];
1158-
$this->entityStates[$oid] = self::STATE_MANAGED;
1159-
$this->originalEntityData[$oid][$idField] = $idValue;
1160-
1161-
$this->addToIdentityMap($entity);
1155+
$this->assignPostInsertId($postInsertId['entity'], $postInsertId['generatedId']);
11621156
}
1163-
} else {
1164-
foreach ($insertionsForClass as $oid => $entity) {
1165-
if (! isset($this->entityIdentifiers[$oid])) {
1166-
//entity was not added to identity map because some identifiers are foreign keys to new entities.
1167-
//add it now
1168-
$this->addToEntityIdentifiersAndEntityMap($class, $oid, $entity);
1169-
}
1157+
}
1158+
1159+
foreach ($insertionsForClass as $oid => $entity) {
1160+
if (! isset($this->entityIdentifiers[$oid])) {
1161+
//entity was not added to identity map because some identifiers are foreign keys to new entities.
1162+
//add it now
1163+
$this->addToEntityIdentifiersAndEntityMap($class, $oid, $entity);
11701164
}
11711165
}
11721166

@@ -3790,4 +3784,30 @@ private function normalizeIdentifier(ClassMetadata $targetClass, array $flatIden
37903784

37913785
return $normalizedAssociatedId;
37923786
}
3787+
3788+
/**
3789+
* Assign a post-insert generated ID to an entity
3790+
*
3791+
* This is used by EntityPersisters after they inserted entities into the database.
3792+
* It will place the assigned ID values in the entity's fields and start tracking
3793+
* the entity in the identity map.
3794+
*
3795+
* @param object $entity
3796+
* @param mixed $generatedId
3797+
*/
3798+
final public function assignPostInsertId($entity, $generatedId): void
3799+
{
3800+
$class = $this->em->getClassMetadata(get_class($entity));
3801+
$idField = $class->getSingleIdentifierFieldName();
3802+
$idValue = $this->convertSingleFieldIdentifierToPHPValue($class, $generatedId);
3803+
$oid = spl_object_id($entity);
3804+
3805+
$class->reflFields[$idField]->setValue($entity, $idValue);
3806+
3807+
$this->entityIdentifiers[$oid] = [$idField => $idValue];
3808+
$this->entityStates[$oid] = self::STATE_MANAGED;
3809+
$this->originalEntityData[$oid][$idField] = $idValue;
3810+
3811+
$this->addToIdentityMap($entity);
3812+
}
37933813
}

tests/Doctrine/Tests/ORM/Persisters/JoinedSubclassPersisterTest.php

-38
This file was deleted.

0 commit comments

Comments
 (0)