Skip to content

Commit 6863272

Browse files
committed
Merge remote-tracking branch 'origin/3.5.x' into 3.6.x
2 parents c472a15 + eae6577 commit 6863272

File tree

12 files changed

+311
-137
lines changed

12 files changed

+311
-137
lines changed

UPGRADE.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,32 @@
1+
Note about upgrading: Doctrine uses static and runtime mechanisms to raise
2+
awareness about deprecated code.
3+
4+
- Use of `@deprecated` docblock that is detected by IDEs (like PHPStorm) or
5+
Static Analysis tools (like Psalm, phpstan)
6+
- Use of our low-overhead runtime deprecation API, details:
7+
https://github.com/doctrine/deprecations/
8+
9+
# Upgrade to 3.x General Notes
10+
11+
We recommend you upgrade to DBAL 3 first before upgrading to ORM 3. See
12+
the DBAL upgrade docs: https://github.com/doctrine/dbal/blob/3.10.x/UPGRADE.md
13+
14+
Rather than doing several major upgrades at once, we recommend you do the following:
15+
16+
- upgrade to DBAL 3
17+
- deploy and monitor
18+
- upgrade to ORM 3
19+
- deploy and monitor
20+
- upgrade to DBAL 4
21+
- deploy and monitor
22+
23+
If you are using Symfony, the recommended minimal Doctrine Bundle version is 2.15
24+
to run with ORM 3.
25+
26+
At this point, we recommend upgrading to PHP 8.4 first and then directly from
27+
ORM 2.19 to 3.5 and up so that you can skip the lazy ghost proxy generation
28+
and directly start using native lazy objects.
29+
130
# Upgrade to 3.6
231

332
## Deprecate specifying `nullable` on columns that end up being used in a primary key
@@ -40,6 +69,8 @@ root alias as key.
4069

4170
# Upgrade to 3.5
4271

72+
See the General notes to upgrading to 3.x versions above.
73+
4374
## Deprecate not using native lazy objects on PHP 8.4+
4475

4576
Having native lazy objects disabled on PHP 8.4+ is deprecated and will not be
@@ -93,6 +124,8 @@ decide to remove it before it is used too widely.
93124

94125
# Upgrade to 3.4
95126

127+
See the General notes to upgrading to 3.x versions above.
128+
96129
## Discriminator Map class duplicates
97130

98131
Using the same class several times in a discriminator map is deprecated.
@@ -113,6 +146,8 @@ Companion accessor methods are deprecated as well.
113146

114147
# Upgrade to 3.3
115148

149+
See the General notes to upgrading to 3.x versions above.
150+
116151
## Deprecate `DatabaseDriver`
117152

118153
The class `Doctrine\ORM\Mapping\Driver\DatabaseDriver` is deprecated without replacement.
@@ -129,6 +164,8 @@ method. Details can be found at https://github.com/doctrine/orm/pull/11188.
129164

130165
# Upgrade to 3.2
131166

167+
See the General notes to upgrading to 3.x versions above.
168+
132169
## Deprecate the `NotSupported` exception
133170

134171
The class `Doctrine\ORM\Exception\NotSupported` is deprecated without replacement.
@@ -155,6 +192,8 @@ using the `\Doctrine\ORM\Mapping\UniqueConstraint` and `\Doctrine\ORM\Mapping\In
155192

156193
# Upgrade to 3.1
157194

195+
See the General notes to upgrading to 3.x versions above.
196+
158197
## Deprecate `Doctrine\ORM\Mapping\ReflectionEnumProperty`
159198

160199
This class is deprecated and will be removed in 4.0.
@@ -178,6 +217,8 @@ Using array access on instances of the following classes is deprecated:
178217

179218
# Upgrade to 3.0
180219

220+
See the General notes to upgrading to 3.x versions above.
221+
181222
## BC BREAK: Calling `ClassMetadata::getAssociationMappedByTargetField()` with the owning side of an association now throws an exception
182223

183224
Previously, calling
@@ -203,6 +244,9 @@ so `$targetEntity` is a first argument now. This change affects only non-named a
203244
When using the `AUTO` strategy to let Doctrine determine the identity generation mechanism for
204245
an entity, and when using `doctrine/dbal` 4, PostgreSQL now uses `IDENTITY`
205246
instead of `SEQUENCE` or `SERIAL`.
247+
248+
There are three ways to handle this change.
249+
206250
* If you want to upgrade your existing tables to identity columns, you will need to follow [migration to identity columns on PostgreSQL](https://www.doctrine-project.org/projects/doctrine-dbal/en/4.0/how-to/postgresql-identity-migration.html)
207251
* If you want to keep using SQL sequences, you need to configure the ORM this way:
208252
```php
@@ -215,6 +259,27 @@ $configuration->setIdentityGenerationPreferences([
215259
PostgreSQLPlatform::CLASS => ClassMetadata::GENERATOR_TYPE_SEQUENCE,
216260
]);
217261
```
262+
* You can change individual entities to use the `SEQUENCE` strategy instead of `AUTO`:
263+
```php
264+
265+
diff --git a/src/Entity/Example.php b/src/Entity/Example.php
266+
index 28be8df378..3b7d61bda6 100644
267+
--- a/src/Entity/Example.php
268+
+++ b/src/Entity/Example.php
269+
@@ -38,7 +38,7 @@ class Example
270+
271+
#[ORM\Id]
272+
#[ORM\Column(type: 'integer')]
273+
- #[ORM\GeneratedValue(strategy: 'AUTO')]
274+
+ #[ORM\GeneratedValue(strategy: 'SEQUENCE')]
275+
private int $id;
276+
277+
#[Assert\Length(max: 255)]
278+
```
279+
The later two options require a small database migration that will remove the default
280+
expression fetching the next value from the sequence. It's not strictly necessary to
281+
do this migration because the code will work anyway. A benefit of this approach is
282+
that you can just make and roll out the code changes first and then migrate the database later.
218283

219284
## BC BREAK: Throw exceptions when using illegal attributes on Embeddable
220285

phpstan-baseline.neon

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3268,31 +3268,25 @@ parameters:
32683268
path: src/Tools/SchemaTool.php
32693269

32703270
-
3271-
message: '#^Parameter \#1 \$columnNames of method Doctrine\\DBAL\\Schema\\Table\:\:setPrimaryKey\(\) expects non\-empty\-list\<string\>, array\<string\> given\.$#'
3272-
identifier: argument.type
3273-
count: 1
3274-
path: src/Tools/SchemaTool.php
3275-
3276-
-
3277-
message: '#^Parameter \#1 \$value of static method Doctrine\\DBAL\\Schema\\Name\\Identifier\:\:unquoted\(\) expects non\-empty\-string, string given\.$#'
3271+
message: '#^Parameter \#2 \$columns of class Doctrine\\DBAL\\Schema\\Index constructor expects non\-empty\-list\<string\>, list\<string\> given\.$#'
32783272
identifier: argument.type
32793273
count: 1
32803274
path: src/Tools/SchemaTool.php
32813275

32823276
-
3283-
message: '#^Parameter \#2 \$columnNames of class Doctrine\\DBAL\\Schema\\PrimaryKeyConstraint constructor expects non\-empty\-list\<Doctrine\\DBAL\\Schema\\Name\\UnqualifiedName\>, list\<Doctrine\\DBAL\\Schema\\Name\\UnqualifiedName\> given\.$#'
3277+
message: '#^Parameter \#2 \$localColumnNames of method Doctrine\\DBAL\\Schema\\Table\:\:addForeignKeyConstraint\(\) expects non\-empty\-list\<string\>, list\<string\> given\.$#'
32843278
identifier: argument.type
32853279
count: 1
32863280
path: src/Tools/SchemaTool.php
32873281

32883282
-
3289-
message: '#^Parameter \#2 \$columns of class Doctrine\\DBAL\\Schema\\Index constructor expects non\-empty\-list\<string\>, list\<string\> given\.$#'
3283+
message: '#^Parameter \#2 \$primaryKeyColumns of method Doctrine\\ORM\\Tools\\SchemaTool\:\:addPrimaryKeyConstraint\(\) expects non\-empty\-array\<non\-empty\-string\>, list\<string\> given\.$#'
32903284
identifier: argument.type
3291-
count: 1
3285+
count: 2
32923286
path: src/Tools/SchemaTool.php
32933287

32943288
-
3295-
message: '#^Parameter \#2 \$localColumnNames of method Doctrine\\DBAL\\Schema\\Table\:\:addForeignKeyConstraint\(\) expects non\-empty\-list\<string\>, list\<string\> given\.$#'
3289+
message: '#^Parameter \#2 \$primaryKeyColumns of method Doctrine\\ORM\\Tools\\SchemaTool\:\:addPrimaryKeyConstraint\(\) expects non\-empty\-array\<non\-empty\-string\>, non\-empty\-list\<string\> given\.$#'
32963290
identifier: argument.type
32973291
count: 1
32983292
path: src/Tools/SchemaTool.php

phpstan-dbal3.neon

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ parameters:
3434
message: '~^Call to an undefined method Doctrine\\DBAL\\Schema\\Table::addPrimaryKeyConstraint\(\)\.$~'
3535
path: src/Tools/SchemaTool.php
3636

37+
-
38+
message: '~^Call to static method quoted\(\) on an unknown class Doctrine\\DBAL\\Schema\\Name\\Identifier\.$~'
39+
path: src/Tools/SchemaTool.php
40+
41+
-
42+
message: '~^Call to an undefined method Doctrine\\DBAL\\Schema\\Table\:\:getObjectName\(\)\.$~'
43+
path: src/Mapping/Driver/DatabaseDriver.php
44+
3745
-
3846
message: '~^Call to an undefined method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint::get.*\.$~'
3947
identifier: method.notFound

src/AbstractQuery.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
use Doctrine\ORM\Mapping\MappingException as ORMMappingException;
1919
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
2020
use Doctrine\ORM\Query\Parameter;
21-
use Doctrine\ORM\Query\QueryException;
2221
use Doctrine\ORM\Query\ResultSetMapping;
2322
use Doctrine\Persistence\Mapping\MappingException;
2423
use LogicException;
@@ -865,10 +864,6 @@ public function toIterable(
865864
throw new LogicException('Uninitialized result set mapping.');
866865
}
867866

868-
if ($rsm->isMixed && count($rsm->scalarMappings) > 0) {
869-
throw QueryException::iterateWithMixedResultNotAllowed();
870-
}
871-
872867
$stmt = $this->_doExecute();
873868

874869
return $this->em->newHydrator($this->hydrationMode)->toIterable($stmt, $rsm, $this->hints);

src/Internal/Hydration/AbstractHydrator.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@
2323
use function array_map;
2424
use function array_merge;
2525
use function count;
26+
use function current;
2627
use function end;
2728
use function in_array;
2829
use function is_array;
30+
use function is_object;
2931
use function ksort;
3032

3133
/**
@@ -126,8 +128,10 @@ final public function toIterable(Result $stmt, ResultSetMapping $resultSetMappin
126128
} else {
127129
yield from $result;
128130
}
129-
} else {
131+
} elseif (is_object(current($result))) {
130132
yield $result;
133+
} else {
134+
yield array_merge(...$result);
131135
}
132136
}
133137
} finally {

src/Mapping/Driver/DatabaseDriver.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,14 @@ public function loadMetadataForClass(string $className, PersistenceClassMetadata
252252
];
253253
}
254254
} else {
255-
$associationMapping['mappedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current(self::getReferencingColumnNames($myFk)), true);
255+
$associationMapping['mappedBy'] = $this->getFieldNameForColumn(
256+
// @phpstan-ignore function.alreadyNarrowedType (DBAL 3 compatibility)
257+
method_exists(Table::class, 'getObjectName')
258+
? $manyTable->getObjectName()->toString()
259+
: $manyTable->getName(), // DBAL < 4.4
260+
current(self::getReferencingColumnNames($myFk)),
261+
true,
262+
);
256263
}
257264

258265
$metadata->mapManyToMany($associationMapping);

src/Tools/SchemaTool.php

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
use function array_flip;
4040
use function array_intersect_key;
4141
use function array_map;
42+
use function array_values;
4243
use function assert;
4344
use function class_exists;
4445
use function count;
@@ -47,6 +48,7 @@
4748
use function in_array;
4849
use function is_numeric;
4950
use function method_exists;
51+
use function preg_match;
5052
use function strtolower;
5153

5254
/**
@@ -971,20 +973,26 @@ private function createSchemaForComparison(Schema $toSchema): Schema
971973
}
972974
}
973975

974-
/** @param string[] $primaryKeyColumns */
976+
/** @param non-empty-array<non-empty-string> $primaryKeyColumns */
975977
private function addPrimaryKeyConstraint(Table $table, array $primaryKeyColumns): void
976978
{
977-
if (class_exists(PrimaryKeyConstraint::class)) {
978-
$primaryKeyColumnNames = [];
979+
if (! class_exists(PrimaryKeyConstraint::class)) {
980+
$table->setPrimaryKey(array_values($primaryKeyColumns));
979981

980-
foreach ($primaryKeyColumns as $primaryKeyColumn) {
982+
return;
983+
}
984+
985+
$primaryKeyColumnNames = [];
986+
987+
foreach ($primaryKeyColumns as $primaryKeyColumn) {
988+
if (preg_match('/^"(.+)"$/', $primaryKeyColumn, $matches) === 1) {
989+
$primaryKeyColumnNames[] = new UnqualifiedName(Identifier::quoted($matches[1]));
990+
} else {
981991
$primaryKeyColumnNames[] = new UnqualifiedName(Identifier::unquoted($primaryKeyColumn));
982992
}
983-
984-
$table->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, $primaryKeyColumnNames, true));
985-
} else {
986-
$table->setPrimaryKey($primaryKeyColumns);
987993
}
994+
995+
$table->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, $primaryKeyColumnNames, true));
988996
}
989997

990998
/** @return string[] */

0 commit comments

Comments
 (0)