UPGRADE.md
Note about upgrading: Doctrine uses static and runtime mechanisms to raise awareness about deprecated code.
#[Deprecated] attribute that is detected by IDEs (like PHPStorm) or
Static Analysis tools (like Psalm, phpstan)Order enumPHP 8.6 provides a native \SortDirection enum that should be used instead of
the Doctrine\Common\Collections\Order enum. The Order enum is deprecated
and will be removed in 4.0.
\SortDirection is polyfilled by the symfony/polyfill-php86 package, that we
require.
As a consequence, Criteria::orderings(), which returns an array of Order
instances, is deprecated in favor of Criteria::getOrderings(), which returns
an array of \SortDirection instances.
ReadableCollection now extends SelectableThe Doctrine\Common\Collections\ReadableCollection interface now extends
Doctrine\Common\Collections\Selectable. Any class implementing
ReadableCollection must also implement Selectable.
The following classes are now readonly classes, making all their properties immutable:
Doctrine\Common\Collections\Expr\ComparisonDoctrine\Common\Collections\Expr\CompositeExpressionDoctrine\Common\Collections\Expr\ValueThe following classes are now final and can no longer be extended:
Doctrine\Common\Collections\CriteriaDoctrine\Common\Collections\Expr\ClosureExpressionVisitorDoctrine\Common\Collections\Expr\ComparisonDoctrine\Common\Collections\Expr\CompositeExpressionDoctrine\Common\Collections\Expr\ValueDoctrine\Common\Collections\ExpressionBuilderDoctrine\Common\Collections\Selectable interface) accesses fields through raw field access onlyWhen using the criteria filtering API properties will be accessed directly through reflection, also bypassing property hooks.
The $accessRawFieldValues parameter in the following methods is now a no-op and can be removed in calling code:
Doctrine\Common\Collections\Criteria::__construct()Doctrine\Common\Collections\Criteria::create()Doctrine\Common\Collections\Expr\ClosureExpressionVisitor::getObjectFieldValue()Doctrine\Common\Collections\Expr\ClosureExpressionVisitor::sortByField()Passing null as $firstResult to
Doctrine\Common\Collections\Criteria::__construct() and to
Doctrine\Common\Collections\Criteria::setFirstResult() is no longer possible.
Use 0 instead.
Criteria orderings direction is now represented by the
Doctrine\Common\Collection\Order enum.
As a consequence:
Criteria::ASC and Criteria::DESC are removed in favor of
Order::Ascending and Order::Descending, respectively.Criteria::getOrderings() is removed in favor of Criteria::orderings(),
which returns array<string, Order>.Criteria::orderBy() no longer accepts array<string, string>, pass
array<string, Order> instead.Criteria::__construct() no longer accepts array<string, string> as
$orderings, pass array<string, Order> instead.Native return types have been added. The new signatures are already described below in the section about upgrading to 2.0.
When extending Doctrine\Common\Collections\AbstractLazyCollection, the
backing collection initialized in doInitialize() must implement
Doctrine\Common\Collections\Selectable. Initializing with a collection that
does not implement Selectable is deprecated and will throw an exception in 3.0.
Also, implementing ReadableCollection without implementing Selectable
deprecated and will be an error in 3.0.
Extending the following classes is deprecated and will no longer be possible in 3.0:
Doctrine\Common\Collections\CriteriaDoctrine\Common\Collections\Expr\ClosureExpressionVisitorDoctrine\Common\Collections\Expr\ComparisonDoctrine\Common\Collections\Expr\CompositeExpressionDoctrine\Common\Collections\Expr\ValueDoctrine\Common\Collections\ExpressionBuilderDoctrine\Common\Collections\Selectable interface)Starting with the next major version, the only way to access data when using the criteria filtering API is through direct (reflection-based) access at properties directly, also bypassing property hooks. This is to ensure consistency with how the ORM/ODM works. See https://github.com/doctrine/collections/pull/472 for the full motivation.
To opt-in to the new behaviour, pass true for the $accessRawFieldValues parameter when creating a Criteria
object through either Doctrine\Common\Collections\Criteria::create() or when calling the Doctrine\Common\Collections\Criteria constructor.
Be aware that switching to reflection-based field access may prevent ORM or ODM proxy objects
becoming initialized, since their triggers (like calling public methods) are bypassed. This might lead
to null values being read from such objects, which may cause wrong filtering or sorting results.
To avoid this issue, use native lazy objects added in PHP 8.4.
See https://github.com/doctrine/collections/issues/487 for more details on when this may happen.
Criteria orderings direction is now represented by the
Doctrine\Common\Collection\Order enum.
As a consequence:
Criteria::ASC and Criteria::DESC are deprecated in favor of
Order::Ascending and Order::Descending, respectively.Criteria::getOrderings() is deprecated in favor of Criteria::orderings(),
which returns array<string, Order>.Criteria::orderBy() accepts array<string, string|Order>, but passing
anything other than array<string, Order> is deprecated.Native parameter types were added. Native return types will be added in 3.0.x As a consequence, some signatures were changed and will have to be adjusted in sub-classes.
Note that in order to keep compatibility with both 1.x and 2.x versions, extending code would have to omit the added parameter types. This would only work in PHP 7.2+ which is the first version featuring parameter widening. It is also recommended to add return types according to the tables below
You can find a list of major changes to public API below.
| 1.0.x | 3.0.x |
|---|---|
add($element) | add(mixed $element): void |
clear() | clear(): void |
contains($element) | contains(mixed $element): bool |
isEmpty() | isEmpty(): bool |
removeElement($element) | removeElement(mixed $element): bool |
containsKey($key) | containsKey(string|int $key): bool |
get() | get(string|int $key): mixed |
getKeys() | getKeys(): array |
getValues() | getValues(): array |
set($key, $value) | set(string|int $key, $value): void |
toArray() | toArray(): array |
first() | first(): mixed |
last() | last(): mixed |
key() | key(): int|string|null |
current() | current(): mixed |
next() | next(): mixed |
exists(Closure $p) | exists(Closure $p): bool |
filter(Closure $p) | filter(Closure $p): self |
forAll(Closure $p) | forAll(Closure $p): bool |
map(Closure $func) | map(Closure $func): self |
partition(Closure $p) | partition(Closure $p): array |
indexOf($element) | indexOf(mixed $element): int|string|false |
slice($offset, $length = null) | slice(int $offset, ?int $length = null): array |
count() | count(): int |
getIterator() | getIterator(): \Traversable |
offsetSet($offset, $value) | offsetSet(mixed $offset, mixed $value): void |
offsetUnset($offset) | offsetUnset(mixed $offset): void |
offsetExists($offset) | offsetExists(mixed $offset): bool |
| 1.0.x | 3.0.x |
|---|---|
isInitialized() | isInitialized(): bool |
initialize() | initialize(): void |
doInitialize() | doInitialize(): void |
| 1.0.x | 3.0.x |
|---|---|
createFrom(array $elements) | createFrom(array $elements): static |
__toString() | __toString(): string |
| 1.0.x | 3.0.x |
|---|---|
where(Expression $expression): self | where(Expression $expression): static |
andWhere(Expression $expression): self | andWhere(Expression $expression): static |
orWhere(Expression $expression): self | orWhere(Expression $expression): static |
orderBy(array $orderings): self | orderBy(array $orderings): static |
setFirstResult(?int $firstResult): self | setFirstResult(?int $firstResult): static |
setMaxResult(?int $maxResults): self | setMaxResults(?int $maxResults): static |
| 1.0.x | 3.0.x |
|---|---|
matching(Criteria $criteria) | matching(Criteria $criteria): Collection |
Passing null as $firstResult to
Doctrine\Common\Collections\Criteria::__construct() and to
Doctrine\Common\Collections\Criteria::setFirstResult() is deprecated.
Use 0 instead.