](https://www.doctrine-project.org/stop-war.html)
-
-Doctrine ORM is an object-relational mapper for PHP 7.1+ that provides transparent persistence
+Doctrine ORM is an object-relational mapper for PHP 8.1+ that provides transparent persistence
for PHP objects. It sits on top of a powerful database abstraction layer (DBAL). One of its key features
is the option to write database queries in a proprietary object oriented SQL dialect called Doctrine Query Language (DQL),
inspired by Hibernate's HQL. This provides developers with a powerful alternative to SQL that maintains flexibility
diff --git a/UPGRADE.md b/UPGRADE.md
index 9de8af04d38..085f645c3f5 100644
--- a/UPGRADE.md
+++ b/UPGRADE.md
@@ -1,4 +1,13 @@
-# Upgrade to 2.20
+# Upgrade to 3.4
+
+Using the same class several times in a discriminator map is deprecated.
+In 4.0, this will be an error.
+
+# Upgrade to 3.3
+
+## Deprecate `DatabaseDriver`
+
+The class `Doctrine\ORM\Mapping\Driver\DatabaseDriver` is deprecated without replacement.
## Add `Doctrine\ORM\Query\OutputWalker` interface, deprecate `Doctrine\ORM\Query\SqlWalker::getExecutor()`
@@ -9,6 +18,775 @@ The output walker must not base its workings on the query `firstResult`/`maxResu
Any operation dependent on `firstResult`/`maxResult` should take place within the `SqlFinalizer::createExecutor()`
method. Details can be found at https://github.com/doctrine/orm/pull/11188.
+
+# Upgrade to 3.2
+
+## Deprecate the `NotSupported` exception
+
+The class `Doctrine\ORM\Exception\NotSupported` is deprecated without replacement.
+
+## Deprecate remaining `Serializable` implementation
+
+Relying on `SequenceGenerator` implementing the `Serializable` is deprecated
+because that interface won't be implemented in ORM 4 anymore.
+
+The following methods are deprecated:
+
+* `SequenceGenerator::serialize()`
+* `SequenceGenerator::unserialize()`
+
+## `orm:schema-tool:update` option `--complete` is deprecated
+
+That option behaves as a no-op, and is deprecated. It will be removed in 4.0.
+
+## Deprecate properties `$indexes` and `$uniqueConstraints` of `Doctrine\ORM\Mapping\Table`
+
+The properties `$indexes` and `$uniqueConstraints` have been deprecated since they had no effect at all.
+The preferred way of defining indices and unique constraints is by
+using the `\Doctrine\ORM\Mapping\UniqueConstraint` and `\Doctrine\ORM\Mapping\Index` attributes.
+
+# Upgrade to 3.1
+
+## Deprecate `Doctrine\ORM\Mapping\ReflectionEnumProperty`
+
+This class is deprecated and will be removed in 4.0.
+Instead, use `Doctrine\Persistence\Reflection\EnumReflectionProperty` from
+`doctrine/persistence`.
+
+## Deprecate passing null to `ClassMetadata::fullyQualifiedClassName()`
+
+Passing `null` to `Doctrine\ORM\ClassMetadata::fullyQualifiedClassName()` is
+deprecated and will no longer be possible in 4.0.
+
+## Deprecate array access
+
+Using array access on instances of the following classes is deprecated:
+
+- `Doctrine\ORM\Mapping\DiscriminatorColumnMapping`
+- `Doctrine\ORM\Mapping\EmbedClassMapping`
+- `Doctrine\ORM\Mapping\FieldMapping`
+- `Doctrine\ORM\Mapping\JoinColumnMapping`
+- `Doctrine\ORM\Mapping\JoinTableMapping`
+
+# Upgrade to 3.0
+
+## BC BREAK: Calling `ClassMetadata::getAssociationMappedByTargetField()` with the owning side of an association now throws an exception
+
+Previously, calling
+`Doctrine\ORM\Mapping\ClassMetadata::getAssociationMappedByTargetField()` with
+the owning side of an association returned `null`, which was undocumented, and
+wrong according to the phpdoc of the parent method.
+
+If you do not know whether you are on the owning or inverse side of an association,
+you can use `Doctrine\ORM\Mapping\ClassMetadata::isAssociationInverseSide()`
+to find out.
+
+## BC BREAK: `Doctrine\ORM\Proxy\Autoloader` no longer extends `Doctrine\Common\Proxy\Autoloader`
+
+Make sure to use the former when writing a type declaration or an `instanceof` check.
+
+## Minor BC BREAK: Changed order of arguments passed to `OneToOne`, `ManyToOne` and `Index` mapping PHP attributes
+
+To keep PHP mapping attributes consistent, order of arguments passed to above attributes has been changed
+so `$targetEntity` is a first argument now. This change affects only non-named arguments usage.
+
+## BC BREAK: AUTO keyword for identity generation defaults to IDENTITY for PostgreSQL when using `doctrine/dbal` 4
+
+When using the `AUTO` strategy to let Doctrine determine the identity generation mechanism for
+an entity, and when using `doctrine/dbal` 4, PostgreSQL now uses `IDENTITY`
+instead of `SEQUENCE` or `SERIAL`.
+* 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)
+* If you want to keep using SQL sequences, you need to configure the ORM this way:
+```php
+use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
+use Doctrine\ORM\Configuration;
+use Doctrine\ORM\Mapping\ClassMetadata;
+
+assert($configuration instanceof Configuration);
+$configuration->setIdentityGenerationPreferences([
+ PostgreSQLPlatform::CLASS => ClassMetadata::GENERATOR_TYPE_SEQUENCE,
+]);
+```
+
+## BC BREAK: Throw exceptions when using illegal attributes on Embeddable
+
+There are only a few attributes allowed on an embeddable such as `#[Column]` or
+`#[Embedded]`. Previously all others that target entity classes where ignored,
+now they throw an exception.
+
+## BC BREAK: Partial objects are removed
+
+WARNING: This was relaxed in ORM 3.2 when partial was re-allowed for array-hydration.
+
+- The `PARTIAL` keyword in DQL no longer exists (reintroduced in ORM 3.2)
+- `Doctrine\ORM\Query\AST\PartialObjectExpression` is removed. (reintroduced in ORM 3.2)
+- `Doctrine\ORM\Query\SqlWalker::HINT_PARTIAL` (reintroduced in ORM 3.2) and
+ `Doctrine\ORM\Query::HINT_FORCE_PARTIAL_LOAD` are removed.
+- `Doctrine\ORM\EntityManager*::getPartialReference()` is removed.
+
+## BC BREAK: Enforce ArrayCollection Type on `\Doctrine\ORM\QueryBuilder::setParameters(ArrayCollection $parameters)`
+
+The argument $parameters can no longer be a key=>value array. Only ArrayCollection types are allowed.
+
+### Before
+
+```php
+$qb = $em->createQueryBuilder()
+ ->select('u')
+ ->from('User', 'u')
+ ->where('u.id = :user_id1 OR u.id = :user_id2')
+ ->setParameters(array(
+ 'user_id1' => 1,
+ 'user_id2' => 2
+ ));
+```
+
+### After
+
+```php
+$qb = $em->createQueryBuilder()
+ ->select('u')
+ ->from('User', 'u')
+ ->where('u.id = :user_id1 OR u.id = :user_id2')
+ ->setParameters(new ArrayCollection(array(
+ new Parameter('user_id1', 1),
+ new Parameter('user_id2', 2)
+ )));
+```
+
+## BC BREAK: `Doctrine\ORM\Persister\Entity\EntityPersister::executeInserts()` return type changed to `void`
+
+Implementors should adapt to the new signature, and should call
+`UnitOfWork::assignPostInsertId()` for each entry in the previously returned
+array.
+
+## BC BREAK: `Doctrine\ORM\Proxy\ProxyFactory` no longer extends abstract factory from `doctrine/common`
+
+It is no longer possible to call methods, constants or properties inherited
+from that class on a `ProxyFactory` instance.
+
+`Doctrine\ORM\Proxy\ProxyFactory::createProxyDefinition()` and
+`Doctrine\ORM\Proxy\ProxyFactory::resetUninitializedProxy()` are removed as well.
+
+## BC BREAK: lazy ghosts are enabled unconditionally
+
+`Doctrine\ORM\Configuration::setLazyGhostObjectEnabled()` and
+`Doctrine\ORM\Configuration::isLazyGhostObjectEnabled()` are now no-ops and
+will be deprecated in 3.1.0
+
+## BC BREAK: collisions in identity map are unconditionally rejected
+
+`Doctrine\ORM\Configuration::setRejectIdCollisionInIdentityMap()` and
+`Doctrine\ORM\Configuration::isRejectIdCollisionInIdentityMapEnabled()` are now
+no-ops and will be deprecated in 3.1.0.
+
+## BC BREAK: Lifecycle callback mapping on embedded classes is now explicitly forbidden
+
+Lifecycle callback mapping on embedded classes produced no effect, and is now
+explicitly forbidden to point out mistakes.
+
+## BC BREAK: The `NOTIFY` change tracking policy is removed
+
+You should use `DEFERRED_EXPLICIT` instead.
+
+## BC BREAK: `Mapping\Driver\XmlDriver::__construct()` third argument is now enabled by default
+
+The third argument to
+`Doctrine\ORM\Mapping\Driver\XmlDriver::__construct()` was introduced to
+let users opt-in to XML validation, that is now always enabled by default.
+
+As a consequence, the same goes for
+`Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver`, and for
+`Doctrine\ORM\ORMSetup::createXMLMetadataConfiguration()`.
+
+## BC BREAK: `Mapping\Driver\AttributeDriver::__construct()` second argument is now a no-op
+
+The second argument to
+`Doctrine\ORM\Mapping\Driver\AttributeDriver::__construct()` was introduced to
+let users opt-in to a new behavior, that is now always enforced, regardless of
+the value of that argument.
+
+## BC BREAK: `Query::setDQL()` and `Query::setFirstResult()` no longer accept `null`
+
+The `$dqlQuery` argument of `Doctrine\ORM\Query::setDQL()` must always be a
+string.
+
+The `$firstResult` argument of `Doctrine\ORM\Query::setFirstResult()` must
+always be an integer.
+
+## BC BREAK: `orm:schema-tool:update` option `--complete` is now a no-op
+
+`orm:schema-tool:update` now behaves as if `--complete` was provided,
+regardless of whether it is provided or not.
+
+## BC BREAK: Removed `Doctrine\ORM\Proxy\Proxy` interface.
+
+Use `Doctrine\Persistence\Proxy` instead to check whether proxies are initialized.
+
+## BC BREAK: Overriding fields or associations declared in other than mapped superclasses
+
+As stated in the documentation, fields and associations may only be overridden when being inherited
+from mapped superclasses. Overriding them for parent entity classes now throws a `MappingException`.
+
+## BC BREAK: Undeclared entity inheritance now throws a `MappingException`
+
+As soon as an entity class inherits from another entity class, inheritance has to
+be declared by adding the appropriate configuration for the root entity.
+
+## Removed `getEntityManager()` in `Doctrine\ORM\Event\OnClearEventArgs` and `Doctrine\ORM\Event\*FlushEventArgs`
+
+Use `getObjectManager()` instead.
+
+## BC BREAK: Removed `Doctrine\ORM\Mapping\ClassMetadataInfo` class
+
+Use `Doctrine\ORM\Mapping\ClassMetadata` instead.
+
+## BC BREAK: Removed `Doctrine\ORM\Event\LifecycleEventArgs` class.
+
+Use one of the dedicated event classes instead:
+
+* `Doctrine\ORM\Event\PrePersistEventArgs`
+* `Doctrine\ORM\Event\PreUpdateEventArgs`
+* `Doctrine\ORM\Event\PreRemoveEventArgs`
+* `Doctrine\ORM\Event\PostPersistEventArgs`
+* `Doctrine\ORM\Event\PostUpdateEventArgs`
+* `Doctrine\ORM\Event\PostRemoveEventArgs`
+* `Doctrine\ORM\Event\PostLoadEventArgs`
+
+## BC BREAK: Removed `AttributeDriver::$entityAnnotationClasses` and `AttributeDriver::getReader()`
+
+* If you need to change the behavior of `AttributeDriver::isTransient()`,
+ override that method instead.
+* The attribute reader is internal to the driver and should not be accessed from outside.
+
+## BC BREAK: Removed `Doctrine\ORM\Query\AST\InExpression`
+
+The AST parser will create a `InListExpression` or a `InSubselectExpression` when
+encountering an `IN ()` DQL expression instead of a generic `InExpression`.
+
+As a consequence, `SqlWalker::walkInExpression()` has been replaced by
+`SqlWalker::walkInListExpression()` and `SqlWalker::walkInSubselectExpression()`.
+
+## BC BREAK: Changed `EntityManagerInterface#refresh($entity)`, `EntityManagerDecorator#refresh($entity)` and `UnitOfWork#refresh($entity)` signatures
+
+The new signatures of these methods add an optional `LockMode|int|null $lockMode`
+param with default `null` value (no lock).
+
+## BC Break: Removed AnnotationDriver
+
+The annotation driver and anything related to annotation has been removed.
+Please migrate to another mapping driver.
+
+The `Doctrine\ORM\Mapping\Annotation` maker interface has been removed in favor of the new
+`Doctrine\ORM\Mapping\MappingAttribute` interface.
+
+## BC BREAK: Removed `EntityManager::create()`
+
+The constructor of `EntityManager` is now public and must be used instead of the `create()` method.
+However, the constructor expects a `Connection` while `create()` accepted an array with connection parameters.
+You can pass that array to DBAL's `Doctrine\DBAL\DriverManager::getConnection()` method to bootstrap the
+connection.
+
+## BC BREAK: Removed `QueryBuilder` methods and constants.
+
+The following `QueryBuilder` constants and methods have been removed:
+
+1. `SELECT`,
+2. `DELETE`,
+3. `UPDATE`,
+4. `STATE_DIRTY`,
+5. `STATE_CLEAN`,
+6. `getState()`,
+7. `getType()`.
+
+## BC BREAK: Omitting only the alias argument for `QueryBuilder::update` and `QueryBuilder::delete` is not supported anymore
+
+When building an UPDATE or DELETE query and when passing a class/type to the function, the alias argument must not be omitted.
+
+### Before
+
+```php
+$qb = $em->createQueryBuilder()
+ ->delete('User u')
+ ->where('u.id = :user_id')
+ ->setParameter('user_id', 1);
+```
+
+### After
+
+```php
+$qb = $em->createQueryBuilder()
+ ->delete('User', 'u')
+ ->where('u.id = :user_id')
+ ->setParameter('user_id', 1);
+```
+
+## BC BREAK: Split output walkers and tree walkers
+
+`SqlWalker` and its child classes don't implement the `TreeWalker` interface
+anymore.
+
+The following methods have been removed from the `TreeWalker` interface and
+from the `TreeWalkerAdapter` and `TreeWalkerChain` classes:
+
+* `setQueryComponent()`
+* `walkSelectClause()`
+* `walkFromClause()`
+* `walkFunction()`
+* `walkOrderByClause()`
+* `walkOrderByItem()`
+* `walkHavingClause()`
+* `walkJoin()`
+* `walkSelectExpression()`
+* `walkQuantifiedExpression()`
+* `walkSubselect()`
+* `walkSubselectFromClause()`
+* `walkSimpleSelectClause()`
+* `walkSimpleSelectExpression()`
+* `walkAggregateExpression()`
+* `walkGroupByClause()`
+* `walkGroupByItem()`
+* `walkDeleteClause()`
+* `walkUpdateClause()`
+* `walkUpdateItem()`
+* `walkWhereClause()`
+* `walkConditionalExpression()`
+* `walkConditionalTerm()`
+* `walkConditionalFactor()`
+* `walkConditionalPrimary()`
+* `walkExistsExpression()`
+* `walkCollectionMemberExpression()`
+* `walkEmptyCollectionComparisonExpression()`
+* `walkNullComparisonExpression()`
+* `walkInExpression()`
+* `walkInstanceOfExpression()`
+* `walkLiteral()`
+* `walkBetweenExpression()`
+* `walkLikeExpression()`
+* `walkStateFieldPathExpression()`
+* `walkComparisonExpression()`
+* `walkInputParameter()`
+* `walkArithmeticExpression()`
+* `walkArithmeticTerm()`
+* `walkStringPrimary()`
+* `walkArithmeticFactor()`
+* `walkSimpleArithmeticExpression()`
+* `walkPathExpression()`
+* `walkResultVariable()`
+* `getExecutor()`
+
+The following changes have been made to the abstract `TreeWalkerAdapter` class:
+
+* The method `setQueryComponent()` is now protected.
+* The method `_getQueryComponents()` has been removed in favor of
+ `getQueryComponents()`.
+
+## BC BREAK: Removed identity columns emulation through sequences
+
+If the platform you are using does not support identity columns, you should
+switch to the `SEQUENCE` strategy.
+
+## BC BREAK: Made setters parameters mandatory
+
+The following methods require an argument when being called. Pass `null`
+instead of omitting the argument.
+
+* `Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs::setFoundMetadata()`
+* `Doctrine\ORM\AbstractQuery::setHydrationCacheProfile()`
+* `Doctrine\ORM\AbstractQuery::setResultCache()`
+* `Doctrine\ORM\AbstractQuery::setResultCacheProfile()`
+
+## BC BREAK: New argument to `NamingStrategy::joinColumnName()`
+
+### Before
+
+```php
+ `Exception\MissingMappingDriverImplementation::create()`
+ * `unrecognizedField()` => `Persisters\Exception\UnrecognizedField::byName()`
+ * `unexpectedAssociationValue()` => `Exception\UnexpectedAssociationValue::create()`
+ * `invalidOrientation()` => `Persisters\Exception\InvalidOrientation::fromClassNameAndField()`
+ * `entityManagerClosed()` => `Exception\EntityManagerClosed::create()`
+ * `invalidHydrationMode()` => `Exception\InvalidHydrationMode::fromMode()`
+ * `mismatchedEventManager()` => `Exception\MismatchedEventManager::create()`
+ * `findByRequiresParameter()` => `Repository\Exception\InvalidMagicMethodCall::onMissingParameter()`
+ * `invalidMagicCall()` => `Repository\Exception\InvalidMagicMethodCall::becauseFieldNotFoundIn()`
+ * `invalidFindByInverseAssociation()` => `Repository\Exception\InvalidFindByCall::fromInverseSideUsage()`
+ * `invalidResultCacheDriver()` => `Cache\Exception\InvalidResultCacheDriver::create()`
+ * `notSupported()` => `Exception\NotSupported::create()`
+ * `queryCacheNotConfigured()` => `QueryCacheNotConfigured::create()`
+ * `metadataCacheNotConfigured()` => `Cache\Exception\MetadataCacheNotConfigured::create()`
+ * `queryCacheUsesNonPersistentCache()` => `Cache\Exception\QueryCacheUsesNonPersistentCache::fromDriver()`
+ * `metadataCacheUsesNonPersistentCache()` => `Cache\Exception\MetadataCacheUsesNonPersistentCache::fromDriver()`
+ * `proxyClassesAlwaysRegenerating()` => `Exception\ProxyClassesAlwaysRegenerating::create()`
+ * `invalidEntityRepository()` => `Exception\InvalidEntityRepository::fromClassName()`
+ * `missingIdentifierField()` => `Exception\MissingIdentifierField::fromFieldAndClass()`
+ * `unrecognizedIdentifierFields()` => `Exception\UnrecognizedIdentifierFields::fromClassAndFieldNames()`
+ * `cantUseInOperatorOnCompositeKeys()` => `Persisters\Exception\CantUseInOperatorOnCompositeKeys::create()`
+
+## BC Break: `CacheException` is no longer a class, but an interface
+
+All methods in `Doctrine\ORM\Cache\CacheException` have been extracted to dedicated exceptions.
+
+ * `updateReadOnlyCollection()` => `Cache\Exception\CannotUpdateReadOnlyCollection::fromEntityAndField()`
+ * `updateReadOnlyEntity()` => `Cache\Exception\CannotUpdateReadOnlyEntity::fromEntity()`
+ * `nonCacheableEntity()` => `Cache\Exception\NonCacheableEntity::fromEntity()`
+ * `nonCacheableEntityAssociation()` => `Cache\Exception\NonCacheableEntityAssociation::fromEntityAndField()`
+
+
+## BC Break: Missing type declaration added for identifier generators
+
+Although undocumented, it was possible to configure a custom repository
+class that implements `ObjectRepository` but does not extend the
+`EntityRepository` base class. Repository classes have to extend
+`EntityRepository` now.
+
+## BC BREAK: Removed support for entity namespace alias
+
+- `EntityManager::getRepository()` no longer accepts the entity namespace alias
+ notation.
+- `Configuration::addEntityNamespace()` and
+ `Configuration::getEntityNamespace()` have been removed.
+
+## BC BREAK: Remove helper methods from `AbstractCollectionPersister`
+
+The following protected methods of
+`Doctrine\ORM\Cache\Persister\Collection\AbstractCollectionPersister`
+have been removed.
+
+* `evictCollectionCache()`
+* `evictElementCache()`
+
+## BC BREAK: `Doctrine\ORM\Query\TreeWalkerChainIterator`
+
+This class has been removed without replacement.
+
+## BC BREAK: Remove quoting methods from `ClassMetadata`
+
+The following methods have been removed from the class metadata because
+quoting is handled by implementations of `Doctrine\ORM\Mapping\QuoteStrategy`:
+
+* `getQuotedIdentifierColumnNames()`
+* `getQuotedColumnName()`
+* `getQuotedTableName()`
+* `getQuotedJoinTableName()`
+
+## BC BREAK: Remove ability to merge detached entities
+
+Merge semantics was a poor fit for the PHP "share-nothing" architecture.
+In addition to that, merging caused multiple issues with data integrity
+in the managed entity graph, which was constantly spawning more edge-case
+bugs/scenarios.
+
+The method `UnitOfWork::merge()` has been removed. The method
+`EntityManager::merge()` will throw an exception on each call.
+
+## BC BREAK: Removed ability to partially flush/commit entity manager and unit of work
+
+The following methods don't accept a single entity or an array of entities anymore:
+
+* `Doctrine\ORM\EntityManager::flush()`
+* `Doctrine\ORM\Decorator\EntityManagerDecorator::flush()`
+* `Doctrine\ORM\UnitOfWork::commit()`
+
+The semantics of `flush()` and `commit()` will remain the same, but the change
+tracking will be performed on all entities managed by the unit of work, and not
+just on the provided entities, as the parameter is now completely ignored.
+
+## BC BREAK: Removed ability to partially clear entity manager and unit of work
+
+* Passing an argument other than `null` to `EntityManager::clear()` will raise
+ an exception.
+* The unit of work cannot be cleared partially anymore. Passing an argument to
+ `UnitOfWork::clear()` does not have any effect anymore; the unit of work is
+ cleared completely.
+* The method `EntityRepository::clear()` has been removed.
+* The methods `getEntityClass()` and `clearsAllEntities()` have been removed
+ from `OnClearEventArgs`.
+
+## BC BREAK: Remove support for Doctrine Cache
+
+The Doctrine Cache library is not supported anymore. The following methods
+have been removed from `Doctrine\ORM\Configuration`:
+
+* `getQueryCacheImpl()`
+* `setQueryCacheImpl()`
+* `getHydrationCacheImpl()`
+* `setHydrationCacheImpl()`
+* `getMetadataCacheImpl()`
+* `setMetadataCacheImpl()`
+
+The methods have been replaced by PSR-6 compatible counterparts
+(just strip the `Impl` suffix from the old name to get the new one).
+
+## BC BREAK: Remove `Doctrine\ORM\Configuration::newDefaultAnnotationDriver`
+
+This functionality has been moved to the new `ORMSetup` class. Call
+`Doctrine\ORM\ORMSetup::createDefaultAnnotationDriver()` to create
+a new annotation driver.
+
+## BC BREAK: Remove `Doctrine\ORM\Tools\Setup`
+
+In our effort to migrate from Doctrine Cache to PSR-6, the `Setup` class which
+accepted a Doctrine Cache instance in each method has been removed.
+
+The replacement is `Doctrine\ORM\ORMSetup` which accepts a PSR-6
+cache instead.
+
+## BC BREAK: Removed named queries
+
+All APIs related to named queries have been removed.
+
+## BC BREAK: Remove old cache accessors and mutators from query classes
+
+The following methods have been removed from `AbstractQuery`:
+
+* `setResultCacheDriver()`
+* `getResultCacheDriver()`
+* `useResultCache()`
+* `getResultCacheLifetime()`
+* `getResultCacheId()`
+
+The following methods have been removed from `Query`:
+
+* `setQueryCacheDriver()`
+* `getQueryCacheDriver()`
+
+## BC BREAK: Remove `Doctrine\ORM\Cache\MultiGetRegion`
+
+The interface has been merged into `Doctrine\ORM\Cache\Region`.
+
+## BC BREAK: Rename `AbstractIdGenerator::generate()` to `generateId()`
+
+* Implementations of `AbstractIdGenerator` have to implement the method
+ `generateId()`.
+* The method `generate()` has been removed from `AbstractIdGenerator`.
+
+## BC BREAK: Remove cache settings inspection
+
+Doctrine does not provide its own cache implementation anymore and relies on
+the PSR-6 standard instead. As a consequence, we cannot determine anymore
+whether a given cache adapter is suitable for a production environment.
+Because of that, functionality that aims to do so has been removed:
+
+* `Configuration::ensureProductionSettings()`
+* the `orm:ensure-production-settings` console command
+
+## BC BREAK: PSR-6-based second level cache
+
+The second level cache has been reworked to consume a PSR-6 cache. Using a
+Doctrine Cache instance is not supported anymore.
+
+* `DefaultCacheFactory`: The constructor expects a PSR-6 cache item pool as
+ second argument now.
+* `DefaultMultiGetRegion`: This class has been removed.
+* `DefaultRegion`:
+ * The constructor expects a PSR-6 cache item pool as second argument now.
+ * The protected `$cache` property is removed.
+ * The properties `$name` and `$lifetime` as well as the constant
+ `REGION_KEY_SEPARATOR` and the method `getCacheEntryKey()` are
+ `private` now.
+ * The method `getCache()` has been removed.
+
+
+## BC Break: Remove `Doctrine\ORM\Mapping\Driver\PHPDriver`
+
+Use `StaticPHPDriver` instead when you want to programmatically configure
+entity metadata.
+
+## BC BREAK: Remove `Doctrine\ORM\EntityManagerInterface#transactional()`
+
+This method has been replaced by `Doctrine\ORM\EntityManagerInterface#wrapInTransaction()`.
+
+## BC BREAK: Removed support for schema emulation.
+
+The ORM no longer attempts to emulate schemas on SQLite.
+
+## BC BREAK: Remove `Setup::registerAutoloadDirectory()`
+
+Use Composer's autoloader instead.
+
+## BC BREAK: Remove YAML mapping drivers.
+
+If your code relies on `YamlDriver` or `SimpleYamlDriver`, you **MUST** migrate to
+attribute, annotation or XML drivers instead.
+
+You can use the `orm:convert-mapping` command to convert your metadata mapping to XML
+_before_ upgrading to 3.0:
+
+```sh
+php doctrine orm:convert-mapping xml /path/to/mapping-path-converted-to-xml
+```
+
+## BC BREAK: Remove code generators and related console commands
+
+These console commands have been removed:
+
+* `orm:convert-d1-schema`
+* `orm:convert-mapping`
+* `orm:generate:entities`
+* `orm:generate-repositories`
+
+These classes have been deprecated:
+
+* `Doctrine\ORM\Tools\ConvertDoctrine1Schema`
+* `Doctrine\ORM\Tools\EntityGenerator`
+* `Doctrine\ORM\Tools\EntityRepositoryGenerator`
+
+The entire `Doctrine\ORM\Tools\Export` namespace has been removed as well.
+
+## BC BREAK: Removed `Doctrine\ORM\Version`
+
+Use Composer's runtime API if you _really_ need to check the version of the ORM package at runtime.
+
+## BC BREAK: EntityRepository::count() signature change
+
+The argument `$criteria` of `Doctrine\ORM\EntityRepository::count()` is now
+optional. Overrides in child classes should be made compatible.
+
+## BC BREAK: changes in exception hierarchy
+
+- `Doctrine\ORM\ORMException` has been removed
+- `Doctrine\ORM\Exception\ORMException` is now an interface
+
+## Variadic methods now use native variadics
+The following methods were using `func_get_args()` to simulate a variadic argument:
+- `Doctrine\ORM\Query\Expr#andX()`
+- `Doctrine\ORM\Query\Expr#orX()`
+- `Doctrine\ORM\QueryBuilder#select()`
+- `Doctrine\ORM\QueryBuilder#addSelect()`
+- `Doctrine\ORM\QueryBuilder#where()`
+- `Doctrine\ORM\QueryBuilder#andWhere()`
+- `Doctrine\ORM\QueryBuilder#orWhere()`
+- `Doctrine\ORM\QueryBuilder#groupBy()`
+- `Doctrine\ORM\QueryBuilder#andGroupBy()`
+- `Doctrine\ORM\QueryBuilder#having()`
+- `Doctrine\ORM\QueryBuilder#andHaving()`
+- `Doctrine\ORM\QueryBuilder#orHaving()`
+A variadic argument is now actually used in their signatures signature (`...$x`).
+Signatures of overridden methods should be changed accordingly
+
+## Minor BC BREAK: removed `Doctrine\ORM\EntityManagerInterface#copy()`
+
+Method `Doctrine\ORM\EntityManagerInterface#copy()` never got its implementation and is removed in 3.0.
+
+## BC BREAK: Removed classes related to UUID and TABLE generator strategies
+
+The following classes have been removed:
+- `Doctrine\ORM\Id\TableGenerator`
+- `Doctrine\ORM\Id\UuidGenerator`
+
+Using the `UUID` strategy for generating identifiers is not supported anymore.
+
+## BC BREAK: Removed `Query::iterate()`
+
+The deprecated method `Query::iterate()` has been removed along with the
+following classes and methods:
+
+- `AbstractHydrator::iterate()`
+- `AbstractHydrator::hydrateRow()`
+- `IterableResult`
+
+Use `toIterable()` instead.
+
+# Upgrade to 2.20
+
+## Add `Doctrine\ORM\Query\OutputWalker` interface, deprecate `Doctrine\ORM\Query\SqlWalker::getExecutor()`
+
+Output walkers should implement the new `\Doctrine\ORM\Query\OutputWalker` interface and create
+`Doctrine\ORM\Query\Exec\SqlFinalizer` instances instead of `Doctrine\ORM\Query\Exec\AbstractSqlExecutor`s.
+The output walker must not base its workings on the query `firstResult`/`maxResult` values, so that the
+`SqlFinalizer` can be kept in the query cache and used regardless of the actual `firstResult`/`maxResult` values.
+Any operation dependent on `firstResult`/`maxResult` should take place within the `SqlFinalizer::createExecutor()`
+method. Details can be found at https://github.com/doctrine/orm/pull/11188.
+
## Explictly forbid property hooks
Property hooks are not supported yet by Doctrine ORM. Until support is added,
@@ -17,7 +795,7 @@ change in behavior.
Progress on this is tracked at https://github.com/doctrine/orm/issues/11624 .
-## PARTIAL DQL syntax is undeprecated
+## PARTIAL DQL syntax is undeprecated
Use of the PARTIAL keyword is not deprecated anymore in DQL, because we will be
able to support PARTIAL objects with PHP 8.4 Lazy Objects and
diff --git a/bin/doctrine b/bin/doctrine
deleted file mode 100755
index 83d38042920..00000000000
--- a/bin/doctrine
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/usr/bin/env php
-register();
-
-$classLoader = new \Doctrine\Common\ClassLoader('Symfony');
-$classLoader->register();
-
-$configFile = getcwd() . DIRECTORY_SEPARATOR . 'cli-config.php';
-
-$helperSet = null;
-if (file_exists($configFile)) {
- if ( ! is_readable($configFile)) {
- trigger_error(
- 'Configuration file [' . $configFile . '] does not have read permission.', E_USER_ERROR
- );
- }
-
- require $configFile;
-
- foreach ($GLOBALS as $helperSetCandidate) {
- if ($helperSetCandidate instanceof \Symfony\Component\Console\Helper\HelperSet) {
- $helperSet = $helperSetCandidate;
- break;
- }
- }
-}
-
-$helperSet = ($helperSet) ?: new \Symfony\Component\Console\Helper\HelperSet();
-
-\Doctrine\ORM\Tools\Console\ConsoleRunner::run($helperSet);
diff --git a/bin/doctrine.bat b/bin/doctrine.bat
deleted file mode 100644
index a91645cc457..00000000000
--- a/bin/doctrine.bat
+++ /dev/null
@@ -1,9 +0,0 @@
-@echo off
-
-if "%PHPBIN%" == "" set PHPBIN=@php_bin@
-if not exist "%PHPBIN%" if "%PHP_PEAR_PHP_BIN%" neq "" goto USE_PEAR_PATH
-GOTO RUN
-:USE_PEAR_PATH
-set PHPBIN=%PHP_PEAR_PHP_BIN%
-:RUN
-"%PHPBIN%" "@bin_dir@\doctrine" %*
diff --git a/bin/doctrine.php b/bin/doctrine.php
deleted file mode 100644
index 2c11fd208da..00000000000
--- a/bin/doctrine.php
+++ /dev/null
@@ -1,62 +0,0 @@
-
@@ -14,6 +13,9 @@
+
+
+
@@ -25,11 +27,11 @@
-
-
+
+ ../../../src
-
-
+
+
diff --git a/ci/github/phpunit/pdo_mysql.xml b/ci/github/phpunit/pdo_mysql.xml
index 23cd676a9db..1db2cd4fb06 100644
--- a/ci/github/phpunit/pdo_mysql.xml
+++ b/ci/github/phpunit/pdo_mysql.xml
@@ -3,9 +3,8 @@
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
beStrictAboutOutputDuringTests="true"
- beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
- convertDeprecationsToExceptions="true"
+ cacheDirectory=".phpunit.cache"
>
@@ -14,6 +13,9 @@
+
+
+
@@ -25,12 +27,11 @@
-
-
+
+ ../../../src
-
-
-
+
+
diff --git a/ci/github/phpunit/pdo_pgsql.xml b/ci/github/phpunit/pdo_pgsql.xml
index 0360be046f5..53f270152b3 100644
--- a/ci/github/phpunit/pdo_pgsql.xml
+++ b/ci/github/phpunit/pdo_pgsql.xml
@@ -3,9 +3,8 @@
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
beStrictAboutOutputDuringTests="true"
- beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
- convertDeprecationsToExceptions="true"
+ cacheDirectory=".phpunit.cache"
>
@@ -25,11 +24,11 @@
-
-
+
+ ../../../src
-
-
+
+
diff --git a/ci/github/phpunit/pdo_sqlite.xml b/ci/github/phpunit/pdo_sqlite.xml
index 35de869baf2..385026dc732 100644
--- a/ci/github/phpunit/pdo_sqlite.xml
+++ b/ci/github/phpunit/pdo_sqlite.xml
@@ -3,9 +3,8 @@
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
beStrictAboutOutputDuringTests="true"
- beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
- convertDeprecationsToExceptions="true"
+ cacheDirectory=".phpunit.cache"
>
@@ -23,11 +22,11 @@
-
-
+
+ ../../../src
-
-
+
+
diff --git a/ci/github/phpunit/pgsql.xml b/ci/github/phpunit/pgsql.xml
index b547f47b488..58225decbe2 100644
--- a/ci/github/phpunit/pgsql.xml
+++ b/ci/github/phpunit/pgsql.xml
@@ -3,9 +3,8 @@
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
beStrictAboutOutputDuringTests="true"
- beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
- convertDeprecationsToExceptions="true"
+ cacheDirectory=".phpunit.cache"
>
@@ -25,11 +24,11 @@
-
-
+
+ ../../../src
-
-
+
+
diff --git a/ci/github/phpunit/sqlite3.xml b/ci/github/phpunit/sqlite3.xml
index 4b5ed70e6dd..a4f313b2e81 100644
--- a/ci/github/phpunit/sqlite3.xml
+++ b/ci/github/phpunit/sqlite3.xml
@@ -3,9 +3,8 @@
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
beStrictAboutOutputDuringTests="true"
- beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
- convertDeprecationsToExceptions="true"
+ cacheDirectory=".phpunit.cache"
>
@@ -23,11 +22,11 @@
-
-
+
+ ../../../src
-
-
+
+
diff --git a/composer.json b/composer.json
index c4de9690eaf..4543c9ba735 100644
--- a/composer.json
+++ b/composer.json
@@ -21,45 +21,36 @@
"sort-packages": true
},
"require": {
- "php": "^7.1 || ^8.0",
+ "php": "^8.1",
"composer-runtime-api": "^2",
"ext-ctype": "*",
- "doctrine/cache": "^1.12.1 || ^2.1.1",
- "doctrine/collections": "^1.5 || ^2.1",
- "doctrine/common": "^3.0.3",
- "doctrine/dbal": "^2.13.1 || ^3.2",
+ "doctrine/collections": "^2.2",
+ "doctrine/dbal": "^3.8.2 || ^4",
"doctrine/deprecations": "^0.5.3 || ^1",
"doctrine/event-manager": "^1.2 || ^2",
"doctrine/inflector": "^1.4 || ^2.0",
"doctrine/instantiator": "^1.3 || ^2",
- "doctrine/lexer": "^2 || ^3",
- "doctrine/persistence": "^2.4 || ^3",
+ "doctrine/lexer": "^3",
+ "doctrine/persistence": "^3.3.1 || ^4",
"psr/cache": "^1 || ^2 || ^3",
- "symfony/console": "^4.2 || ^5.0 || ^6.0 || ^7.0",
- "symfony/polyfill-php72": "^1.23",
- "symfony/polyfill-php80": "^1.16"
+ "symfony/console": "^5.4 || ^6.0 || ^7.0",
+ "symfony/var-exporter": "^6.3.9 || ^7.0"
},
"require-dev": {
- "doctrine/annotations": "^1.13 || ^2",
- "doctrine/coding-standard": "^9.0.2 || ^12.0",
- "phpbench/phpbench": "^0.16.10 || ^1.0",
- "phpstan/extension-installer": "~1.1.0 || ^1.4",
- "phpstan/phpstan": "~1.4.10 || 2.0.3",
- "phpstan/phpstan-deprecation-rules": "^1 || ^2",
- "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6",
+ "doctrine/coding-standard": "^12.0",
+ "phpbench/phpbench": "^1.0",
+ "phpdocumentor/guides-cli": "^1.4",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "2.0.3",
+ "phpstan/phpstan-deprecation-rules": "^2",
+ "phpunit/phpunit": "^10.4.0",
"psr/log": "^1 || ^2 || ^3",
"squizlabs/php_codesniffer": "3.7.2",
- "symfony/cache": "^4.4 || ^5.4 || ^6.4 || ^7.0",
- "symfony/var-exporter": "^4.4 || ^5.4 || ^6.2 || ^7.0",
- "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0"
- },
- "conflict": {
- "doctrine/annotations": "<1.13 || >= 3.0"
+ "symfony/cache": "^5.4 || ^6.2 || ^7.0"
},
"suggest": {
"ext-dom": "Provides support for XSD validation for XML mapping files",
- "symfony/cache": "Provides cache support for Setup Tool with doctrine/cache 2.0",
- "symfony/yaml": "If you want to use YAML Metadata Mapping Driver"
+ "symfony/cache": "Provides cache support for Setup Tool with doctrine/cache 2.0"
},
"autoload": {
"psr-4": { "Doctrine\\ORM\\": "src" }
@@ -71,7 +62,6 @@
"Doctrine\\Performance\\": "tests/Performance"
}
},
- "bin": ["bin/doctrine"],
"archive": {
"exclude": ["!vendor", "tests", "*phpunit.xml", "build.xml", "build.properties", "composer.phar", "vendor/satooshi", "lib/vendor", "*.swp"]
}
diff --git a/docs/en/cookbook/advanced-field-value-conversion-using-custom-mapping-types.rst b/docs/en/cookbook/advanced-field-value-conversion-using-custom-mapping-types.rst
index 67a14c8aa7f..8e7812e21a7 100644
--- a/docs/en/cookbook/advanced-field-value-conversion-using-custom-mapping-types.rst
+++ b/docs/en/cookbook/advanced-field-value-conversion-using-custom-mapping-types.rst
@@ -140,11 +140,6 @@ Now we're going to create the ``point`` type and implement all required methods.
return $value;
}
- public function canRequireSQLConversion()
- {
- return true;
- }
-
public function convertToPHPValueSQL($sqlExpr, AbstractPlatform $platform)
{
return sprintf('AsText(%s)', $sqlExpr);
diff --git a/docs/en/cookbook/aggregate-fields.rst b/docs/en/cookbook/aggregate-fields.rst
index 001d70d34b4..20bfa32896f 100644
--- a/docs/en/cookbook/aggregate-fields.rst
+++ b/docs/en/cookbook/aggregate-fields.rst
@@ -352,7 +352,7 @@ the database using a FOR UPDATE.
use Bank\Entities\Account;
use Doctrine\DBAL\LockMode;
- $account = $em->find(Account::class, $accId, LockMode::PESSIMISTIC_READ);
+ $account = $em->find(Account::class, $accId, LockMode::PESSIMISTIC_WRITE);
Keeping Updates and Deletes in Sync
-----------------------------------
diff --git a/docs/en/cookbook/dql-user-defined-functions.rst b/docs/en/cookbook/dql-user-defined-functions.rst
index b189ed59fcd..e1782e05669 100644
--- a/docs/en/cookbook/dql-user-defined-functions.rst
+++ b/docs/en/cookbook/dql-user-defined-functions.rst
@@ -232,6 +232,33 @@ vendors SQL parser to show us further errors in the parsing
process, for example if the Unit would not be one of the supported
values by MySql.
+Typed functions
+---------------
+By default, result of custom functions is fetched as-is from the database driver.
+If you want to be sure that the type is always the same, then your custom function needs to
+implement ``Doctrine\ORM\Query\AST\TypedExpression``. Then, the result is wired
+through ``Doctrine\DBAL\Types\Type::convertToPhpValue()`` of the ``Type`` returned in ``getReturnType()``.
+
+.. code-block:: php
+
+
-
-The NOTIFY change-tracking policy is the most effective
-change-tracking policy provided by Doctrine but it requires some
-boilerplate code. This recipe will show you how this boilerplate
-code should look like. We will implement it on a
-`Layer Supertype `_
-for all our domain objects.
-
-.. note::
-
- The notify change tracking policy is deprecated and will be removed in ORM 3.0.
- (\ `Details `_)
-
-Implementing NotifyPropertyChanged
-----------------------------------
-
-The NOTIFY policy is based on the assumption that the entities
-notify interested listeners of changes to their properties. For
-that purpose, a class that wants to use this policy needs to
-implement the ``NotifyPropertyChanged`` interface from the
-``Doctrine\Common`` namespace.
-
-.. code-block:: php
-
- listeners[] = $listener;
- }
-
- /** Notifies listeners of a change. */
- protected function onPropertyChanged($propName, $oldValue, $newValue) {
- if ($this->listeners) {
- foreach ($this->listeners as $listener) {
- $listener->propertyChanged($this, $propName, $oldValue, $newValue);
- }
- }
- }
- }
-
-Then, in each property setter of concrete, derived domain classes,
-you need to invoke onPropertyChanged as follows to notify
-listeners:
-
-.. code-block:: php
-
- data) { // check: is it actually modified?
- $this->onPropertyChanged('data', $this->data, $data);
- $this->data = $data;
- }
- }
- }
-
-The check whether the new value is different from the old one is
-not mandatory but recommended. That way you can avoid unnecessary
-updates and also have full control over when you consider a
-property changed.
diff --git a/docs/en/cookbook/mysql-enums.rst b/docs/en/cookbook/mysql-enums.rst
index 5d5e4fd3372..9c4c3b5d822 100644
--- a/docs/en/cookbook/mysql-enums.rst
+++ b/docs/en/cookbook/mysql-enums.rst
@@ -43,13 +43,13 @@ entities:
.. code-block:: php
`
* **Drivers**:
- :doc:`Docblock Annotations ` \|
:doc:`Attributes ` \|
:doc:`XML ` \|
- :doc:`YAML ` \|
:doc:`PHP `
Working with Objects
@@ -75,6 +73,7 @@ Advanced Topics
* :doc:`TypedFieldMapper `
* :doc:`Improving Performance `
* :doc:`Caching `
+* :doc:`Partial Hydration `
* :doc:`Partial Objects `
* :doc:`Change Tracking Policies `
* :doc:`Best Practices `
@@ -112,7 +111,6 @@ Cookbook
* **Implementation**:
:doc:`Array Access ` \|
- :doc:`Notify ChangeTracking Example ` \|
:doc:`Working with DateTime ` \|
:doc:`Validation ` \|
:doc:`Entities in the Session ` \|
diff --git a/docs/en/reference/advanced-configuration.rst b/docs/en/reference/advanced-configuration.rst
index 42a0833aca1..3282bbdb359 100644
--- a/docs/en/reference/advanced-configuration.rst
+++ b/docs/en/reference/advanced-configuration.rst
@@ -111,21 +111,16 @@ Gets or sets the metadata driver implementation that is used by
Doctrine to acquire the object-relational metadata for your
classes.
-There are currently 5 available implementations:
+There are currently 3 available implementations:
- ``Doctrine\ORM\Mapping\Driver\AttributeDriver``
- ``Doctrine\ORM\Mapping\Driver\XmlDriver``
- ``Doctrine\ORM\Mapping\Driver\DriverChain``
-- ``Doctrine\ORM\Mapping\Driver\AnnotationDriver`` (deprecated and will
- be removed in ``doctrine/orm`` 3.0)
-- ``Doctrine\ORM\Mapping\Driver\YamlDriver`` (deprecated and will be
- removed in ``doctrine/orm`` 3.0)
Throughout the most part of this manual the AttributeDriver is
used in the examples. For information on the usage of the
-AnnotationDriver, XmlDriver or YamlDriver please refer to the dedicated
-chapters ``Annotation Reference``, ``XML Mapping`` and ``YAML Mapping``.
+XmlDriver please refer to the dedicated chapter ``XML Mapping``.
The attribute driver can be injected in the ``Doctrine\ORM\Configuration``:
@@ -155,9 +150,9 @@ Metadata Cache (***RECOMMENDED***)
Gets or sets the cache adapter to use for caching metadata
information, that is, all the information you supply via attributes,
-annotations, xml or yaml, so that they do not need to be parsed and
-loaded from scratch on every single request which is a waste of
-resources. The cache implementation must implement the PSR-6
+xml, so that they do not need to be parsed and loaded from scratch on
+every single request which is a waste of resources. The cache
+implementation must implement the PSR-6
``Psr\Cache\CacheItemPoolInterface`` interface.
Usage of a metadata cache is highly recommended.
@@ -425,7 +420,7 @@ Multiple Metadata Sources
When using different components using Doctrine ORM you may end up
with them using two different metadata drivers, for example XML and
-YAML. You can use the MappingDriverChain Metadata implementations to
+PHP. You can use the MappingDriverChain Metadata implementations to
aggregate these drivers based on namespaces:
.. code-block:: php
@@ -435,7 +430,7 @@ aggregate these drivers based on namespaces:
$chain = new MappingDriverChain();
$chain->addDriver($xmlDriver, 'Doctrine\Tests\Models\Company');
- $chain->addDriver($yamlDriver, 'Doctrine\Tests\ORM\Mapping');
+ $chain->addDriver($phpDriver, 'Doctrine\Tests\ORM\Mapping');
Based on the namespace of the entity the loading of entities is
delegated to the appropriate driver. The chain semantics come from
diff --git a/docs/en/reference/annotations-reference.rst b/docs/en/reference/annotations-reference.rst
deleted file mode 100644
index f5cd6677bd1..00000000000
--- a/docs/en/reference/annotations-reference.rst
+++ /dev/null
@@ -1,1389 +0,0 @@
-Annotations Reference
-=====================
-
-.. warning::
- The annotation driver is deprecated and will be removed in version
- 3.0. It is strongly recommended to switch to one of the other
- mapping drivers.
-
-.. note::
-
- To be able to use annotations, you will have to install an extra
- package called ``doctrine/annotations``.
-
-You've probably used docblock annotations in some form already,
-most likely to provide documentation metadata for a tool like
-``PHPDocumentor`` (@author, @link, ...). Docblock annotations are a
-tool to embed metadata inside the documentation section which can
-then be processed by some tool. Doctrine ORM generalizes the concept
-of docblock annotations so that they can be used for any kind of
-metadata and so that it is easy to define new docblock annotations.
-In order to allow more involved annotation values and to reduce the
-chances of clashes with other docblock annotations, the Doctrine ORM
-docblock annotations feature an alternative syntax that is heavily
-inspired by the Annotation syntax introduced in Java 5.
-
-The implementation of these enhanced docblock annotations is located in
-the ``doctrine/annotations`` package, but in the
-``Doctrine\Common\Annotations`` namespace for backwards compatibility
-reasons. Note that ``doctrine/annotations`` is not required by Doctrine
-ORM, and you will need to require that package if you want to use
-annotations. Doctrine ORM docblock annotations support namespaces and
-nested annotations among other things. The Doctrine ORM defines its
-own set of docblock annotations for supplying object-relational mapping
-metadata.
-
-.. note::
-
- If you're not comfortable with the concept of docblock
- annotations, don't worry, as mentioned earlier Doctrine ORM provides
- XML and YAML alternatives and you could easily implement your own
- favourite mechanism for defining ORM metadata.
-
-In this chapter a reference of every Doctrine ORM Annotation is given
-with short explanations on their context and usage.
-
-Index
------
-
-- :ref:`@Column `
-- :ref:`@ColumnResult `
-- :ref:`@Cache `
-- :ref:`@ChangeTrackingPolicy `
-- :ref:`@CustomIdGenerator `
-- :ref:`@DiscriminatorColumn `
-- :ref:`@DiscriminatorMap `
-- :ref:`@Embeddable `
-- :ref:`@Embedded `
-- :ref:`@Entity `
-- :ref:`@EntityResult `
-- :ref:`@FieldResult `
-- :ref:`@GeneratedValue `
-- :ref:`@HasLifecycleCallbacks `
-- :ref:`@Index `
-- :ref:`@Id `
-- :ref:`@InheritanceType `
-- :ref:`@JoinColumn `
-- :ref:`@JoinColumns `
-- :ref:`@JoinTable `
-- :ref:`@ManyToOne `
-- :ref:`@ManyToMany `
-- :ref:`@MappedSuperclass `
-- :ref:`@NamedNativeQuery `
-- :ref:`@OneToOne `
-- :ref:`@OneToMany `
-- :ref:`@OrderBy `
-- :ref:`@PostLoad `
-- :ref:`@PostPersist `
-- :ref:`@PostRemove `
-- :ref:`@PostUpdate `
-- :ref:`@PrePersist `
-- :ref:`@PreRemove `
-- :ref:`@PreUpdate `
-- :ref:`@SequenceGenerator `
-- :ref:`@SqlResultSetMapping `
-- :ref:`@Table `
-- :ref:`@UniqueConstraint `
-- :ref:`@Version `
-
-Reference
----------
-
-.. _annref_column:
-
-@Column
-~~~~~~~
-
-Marks an annotated instance variable as "persistent". It has to be
-inside the instance variables PHP DocBlock comment. Any value hold
-inside this variable will be saved to and loaded from the database
-as part of the lifecycle of the instance variables entity-class.
-
-Required attributes:
-
-- **type**: Name of the Doctrine Type which is converted between PHP
- and Database representation. Default to ``string`` or :ref:`Type from PHP property type `
-
-Optional attributes:
-
-- **name**: By default the property name is used for the database
- column name also, however the 'name' attribute allows you to
- determine the column name.
-
-- **length**: Used by the "string" type to determine its maximum
- length in the database. Doctrine does not validate the length of a
- string value for you.
-
-- **precision**: The precision for a decimal (exact numeric) column
- (applies only for decimal column), which is the maximum number of
- digits that are stored for the values.
-
-- **scale**: The scale for a decimal (exact numeric) column (applies
- only for decimal column), which represents the number of digits
- to the right of the decimal point and must not be greater than
- *precision*.
-
-- **unique**: Boolean value to determine if the value of the column
- should be unique across all rows of the underlying entities table.
-
-- **nullable**: Determines if NULL values allowed for this column. If not specified, default value is false.
-
-- **insertable**: Boolean value to determine if the column should be
- included when inserting a new row into the underlying entities table.
- If not specified, default value is true.
-
-- **updatable**: Boolean value to determine if the column should be
- included when updating the row of the underlying entities table.
- If not specified, default value is true.
-
-- **generated**: An enum with the possible values ALWAYS, INSERT, NEVER. Is
- used after an INSERT or UPDATE statement to determine if the database
- generated this value and it needs to be fetched using a SELECT statement.
-
-- **options**: Array of additional options:
-
- - ``default``: The default value to set for the column if no value
- is supplied.
-
- - ``unsigned``: Boolean value to determine if the column should
- be capable of representing only non-negative integers
- (applies only for integer column and might not be supported by
- all vendors).
-
- - ``fixed``: Boolean value to determine if the specified length of
- a string column should be fixed or varying (applies only for
- string/binary column and might not be supported by all vendors).
-
- - ``comment``: The comment of the column in the schema (might not
- be supported by all vendors).
-
- - ``collation``: The collation of the column (only supported by Drizzle, Mysql, PostgreSQL>=9.1, Sqlite and SQLServer).
-
- - ``check``: Adds a check constraint type to the column (might not
- be supported by all vendors).
-
-- **columnDefinition**: DDL SQL snippet that starts after the column
- name and specifies the complete (non-portable!) column definition.
- This attribute allows to make use of advanced RMDBS features.
- However you should make careful use of this feature and the
- consequences. SchemaTool will not detect changes on the column correctly
- anymore if you use "columnDefinition".
-
- Additionally you should remember that the "type"
- attribute still handles the conversion between PHP and Database
- values. If you use this attribute on a column that is used for
- joins between tables you should also take a look at
- :ref:`@JoinColumn `.
-
-.. note::
-
- For more detailed information on each attribute, please refer to
- the DBAL ``Schema-Representation`` documentation.
-
-Examples:
-
-.. code-block:: php
-
- `
-can be found in the configuration section.
-
-Example:
-
-.. code-block:: php
-
- ` and :ref:`@GeneratedValue(strategy="CUSTOM") ` are specified.
-
-Required attributes:
-
-- **class**: name of the class which should extend Doctrine\ORM\Id\AbstractIdGenerator
-
-Example:
-
-.. code-block:: php
-
- `
-annotation to establish the relationship between the two classes.
-
-.. code-block:: php
-
- `. This
-annotation is optional and only has meaning when used in
-conjunction with @Id.
-
-If this annotation is not specified with @Id the NONE strategy is
-used as default.
-
-Optional attributes:
-
-
-- **strategy**: Set the name of the identifier generation strategy.
- Valid values are ``AUTO``, ``SEQUENCE``, ``IDENTITY``, ``UUID`` (deprecated), ``CUSTOM`` and ``NONE``, explained
- in the :ref:`Identifier Generation Strategies ` section.
- If not specified, default value is AUTO.
-
-Example:
-
-.. code-block:: php
-
- ` annotation on
-the entity-class level. It provides a hint to the SchemaTool to
-generate a database index on the specified table columns. It only
-has meaning in the SchemaTool schema generation context.
-
-Required attributes:
-
-
-- **fields**: Array of fields. Exactly one of **fields**, **columns** is required.
-- **columns**: Array of columns. Exactly one of **fields**, **columns** is required.
-
-Optional attributes:
-
-- **name**: Name of the Index. If not provided, a generated name will be assigned.
-- **options**: Array of platform specific options:
-
- - ``where``: SQL WHERE condition to be used for partial indexes. It will
- only have effect on supported platforms.
-
-Basic example:
-
-.. code-block:: php
-
- ` and
-:ref:`@DiscriminatorColumn ` annotations.
-
-Examples:
-
-.. code-block:: php
-
- `, :ref:`@OneToOne ` fields
-and in the Context of :ref:`@JoinTable ` nested inside
-a @ManyToMany. If this annotation or both *name* and *referencedColumnName*
-are missing they will be computed considering the field's name and the current
-:doc:`naming strategy `.
-
-Optional attributes:
-
-- **name**: Column name that holds the foreign key identifier for
- this relation. In the context of @JoinTable it specifies the column
- name in the join table.
-- **referencedColumnName**: Name of the primary key identifier that
- is used for joining of this relation. Defaults to *id*.
-- **unique**: Determines whether this relation is exclusive between the
- affected entities and should be enforced as such on the database
- constraint level. Defaults to false.
-- **nullable**: Determine whether the related entity is required, or if
- null is an allowed state for the relation. Defaults to true.
-- **onDelete**: Cascade Action (Database-level)
-- **columnDefinition**: DDL SQL snippet that starts after the column
- name and specifies the complete (non-portable!) column definition.
- This attribute enables the use of advanced RMDBS features. Using
- this attribute on @JoinColumn is necessary if you need slightly
- different column definitions for joining columns, for example
- regarding NULL/NOT NULL defaults. However by default a
- "columnDefinition" attribute on :ref:`@Column ` also sets
- the related @JoinColumn's columnDefinition. This is necessary to
- make foreign keys work.
-
-Example:
-
-.. code-block:: php
-
- ` or :ref:`@OneToOne `
-relation with an entity that has multiple identifiers.
-
-.. _annref_jointable:
-
-@JoinTable
-~~~~~~~~~~~~~~
-
-Using :ref:`@OneToMany ` or
-:ref:`@ManyToMany ` on the owning side of the relation
-requires to specify the @JoinTable annotation which describes the
-details of the database join table. If you do not specify
-@JoinTable on these relations reasonable mapping defaults apply
-using the affected table and the column names.
-
-Optional attributes:
-
-
-- **name**: Database name of the join-table
-- **joinColumns**: An array of @JoinColumn annotations describing the
- join-relation between the owning entities table and the join table.
-- **inverseJoinColumns**: An array of @JoinColumn annotations
- describing the join-relation between the inverse entities table and
- the join table.
-
-Example:
-
-.. code-block:: php
-
- ` is an
-additional, optional annotation that has reasonable default
-configuration values using the table and names of the two related
-entities.
-
-Required attributes:
-
-
-- **targetEntity**: FQCN of the referenced target entity. Can be the
- unqualified class name if both classes are in the same namespace.
- *IMPORTANT:* No leading backslash!
-
-Optional attributes:
-
-
-- **mappedBy**: This option specifies the property name on the
- targetEntity that is the owning side of this relation. It is a
- required attribute for the inverse side of a relationship.
-- **inversedBy**: The inversedBy attribute designates the field in the
- entity that is the inverse side of the relationship.
-- **cascade**: Cascade Option
-- **fetch**: One of LAZY, EXTRA_LAZY or EAGER
-- **indexBy**: Index the collection by a field on the target entity.
-
-.. note::
-
- For ManyToMany bidirectional relationships either side may
- be the owning side (the side that defines the @JoinTable and/or
- does not make use of the mappedBy attribute, thus using a default
- join table).
-
-Example:
-
-.. code-block:: php
-
- `.
-
-Optional attributes:
-
-
-- **repositoryClass**: Specifies the FQCN of a subclass of the EntityRepository.
- That will be inherited for all subclasses of that Mapped Superclass.
-
-Example:
-
-.. code-block:: php
-
- ` with one additional option which can
-be specified. The configuration defaults for
-:ref:`@JoinColumn ` using the target entity table and
-primary key column names apply here too.
-
-Required attributes:
-
-
-- **targetEntity**: FQCN of the referenced target entity. Can be the
- unqualified class name if both classes are in the same namespace.
- When typed properties are used it is inherited from PHP type.
- *IMPORTANT:* No leading backslash!
-
-Optional attributes:
-
-
-- **cascade**: Cascade Option
-- **fetch**: One of LAZY or EAGER
-- **orphanRemoval**: Boolean that specifies if orphans, inverse
- OneToOne entities that are not connected to any owning instance,
- should be removed by Doctrine. Defaults to false.
-- **inversedBy**: The inversedBy attribute designates the field in the
- entity that is the inverse side of the relationship.
-
-Example:
-
-.. code-block:: php
-
- ` or :ref:`@OneToMany `
-annotation to specify by which criteria the collection should be
-retrieved from the database by using an ORDER BY clause.
-
-This annotation requires a single non-attributed value with an DQL
-snippet:
-
-Example:
-
-.. code-block:: php
-
- ` annotation on
-the entity-class level. It allows to hint the SchemaTool to
-generate a database unique constraint on the specified table
-columns. It only has meaning in the SchemaTool schema generation
-context.
-
-Required attributes:
-
-
-- **fields**: Array of fields. Exactly one of **fields**, **columns** is required.
-- **columns**: Array of columns. Exactly one of **fields**, **columns** is required.
-
-Optional attributes:
-
-- **name**: Name of the Index. If not provided, a generated name will be assigned.
-- **options**: Array of platform specific options:
-
- - ``where``: SQL WHERE condition to be used for partial indexes. It will
- only have effect on supported platforms.
-
-Basic example:
-
-.. code-block:: php
-
- `
-scenario. It only works on :ref:`@Column ` annotations that have
-the type ``integer`` or ``datetime``. Combining ``@Version`` with
-:ref:`@Id ` is not supported.
-
-Example:
-
-.. code-block:: php
-
-
@@ -87,18 +66,6 @@ A many-to-one association is the most common association between objects. Exampl
- .. code-block:: yaml
-
- User:
- type: entity
- manyToOne:
- address:
- targetEntity: Address
- joinColumn:
- name: address_id
- referencedColumnName: id
-
-
.. note::
The above ``#[JoinColumn]`` is optional as it would default
@@ -154,30 +121,6 @@ references one ``Shipment`` entity.
// ...
}
- .. code-block:: annotation
-
-
@@ -188,17 +131,6 @@ references one ``Shipment`` entity.
- .. code-block:: yaml
-
- Product:
- type: entity
- oneToOne:
- shipment:
- targetEntity: Shipment
- joinColumn:
- name: shipment_id
- referencedColumnName: id
-
Note that the ``#[JoinColumn]`` is not really necessary in this example,
as the defaults would be the same.
@@ -259,38 +191,6 @@ object.
// ...
}
- .. code-block:: annotation
-
-
@@ -304,22 +204,6 @@ object.
- .. code-block:: yaml
-
- Customer:
- oneToOne:
- cart:
- targetEntity: Cart
- mappedBy: customer
- Cart:
- oneToOne:
- customer:
- targetEntity: Customer
- inversedBy: cart
- joinColumn:
- name: customer_id
- referencedColumnName: id
-
Note that the @JoinColumn is not really necessary in this example,
as the defaults would be the same.
@@ -428,41 +312,6 @@ bidirectional many-to-one.
// ...
}
- .. code-block:: annotation
-
-
- * @OneToMany(targetEntity="Feature", mappedBy="product")
- */
- private Collection $features;
- // ...
-
- public function __construct() {
- $this->features = new ArrayCollection();
- }
- }
-
- /** @Entity */
- class Feature
- {
- // ...
- /**
- * Many features have one product. This is the owning side.
- * @ManyToOne(targetEntity="Product", inversedBy="features")
- * @JoinColumn(name="product_id", referencedColumnName="id")
- */
- private Product|null $product = null;
- // ...
- }
-
.. code-block:: xml
@@ -476,24 +325,6 @@ bidirectional many-to-one.
- .. code-block:: yaml
-
- Product:
- type: entity
- oneToMany:
- features:
- targetEntity: Feature
- mappedBy: product
- Feature:
- type: entity
- manyToOne:
- product:
- targetEntity: Product
- inversedBy: features
- joinColumn:
- name: product_id
- referencedColumnName: id
-
Note that the @JoinColumn is not really necessary in this example,
as the defaults would be the same.
@@ -556,39 +387,6 @@ The following example sets up such a unidirectional one-to-many association:
// ...
}
- .. code-block:: annotation
-
-
- */
- private Collection $phonenumbers;
-
- public function __construct()
- {
- $this->phonenumbers = new \Doctrine\Common\Collections\ArrayCollection();
- }
-
- // ...
- }
-
- /** @Entity */
- class Phonenumber
- {
- // ...
- }
-
.. code-block:: xml
@@ -606,24 +404,6 @@ The following example sets up such a unidirectional one-to-many association:
- .. code-block:: yaml
-
- User:
- type: entity
- manyToMany:
- phonenumbers:
- targetEntity: Phonenumber
- joinTable:
- name: users_phonenumbers
- joinColumns:
- user_id:
- referencedColumnName: id
- inverseJoinColumns:
- phonenumber_id:
- referencedColumnName: id
- unique: true
-
-
Generates the following MySQL Schema:
.. code-block:: sql
@@ -684,33 +464,6 @@ database perspective is known as an adjacency list approach.
}
}
- .. code-block:: annotation
-
-
- */
- private Collection $children;
-
- /**
- * Many Categories have One Category.
- * @ManyToOne(targetEntity="Category", inversedBy="children")
- * @JoinColumn(name="parent_id", referencedColumnName="id")
- */
- private Category|null $parent = null;
- // ...
-
- public function __construct() {
- $this->children = new \Doctrine\Common\Collections\ArrayCollection();
- }
- }
-
.. code-block:: xml
@@ -720,19 +473,6 @@ database perspective is known as an adjacency list approach.
- .. code-block:: yaml
-
- Category:
- type: entity
- oneToMany:
- children:
- targetEntity: Category
- mappedBy: parent
- manyToOne:
- parent:
- targetEntity: Category
- inversedBy: children
-
Note that the @JoinColumn is not really necessary in this example,
as the defaults would be the same.
@@ -787,38 +527,6 @@ entities:
// ...
}
- .. code-block:: annotation
-
-
- */
- private Collection $groups;
-
- // ...
-
- public function __construct() {
- $this->groups = new \Doctrine\Common\Collections\ArrayCollection();
- }
- }
-
- /** @Entity */
- class Group
- {
- // ...
- }
-
.. code-block:: xml
@@ -836,22 +544,6 @@ entities:
- .. code-block:: yaml
-
- User:
- type: entity
- manyToMany:
- groups:
- targetEntity: Group
- joinTable:
- name: users_groups
- joinColumns:
- user_id:
- referencedColumnName: id
- inverseJoinColumns:
- group_id:
- referencedColumnName: id
-
Generated MySQL Schema:
.. code-block:: sql
@@ -939,47 +631,6 @@ one is bidirectional.
// ...
}
- .. code-block:: annotation
-
-
- */
- private Collection $groups;
-
- public function __construct() {
- $this->groups = new \Doctrine\Common\Collections\ArrayCollection();
- }
-
- // ...
- }
-
- /** @Entity */
- class Group
- {
- // ...
- /**
- * Many Groups have Many Users.
- * @ManyToMany(targetEntity="User", mappedBy="groups")
- * @var Collection
- */
- private Collection $users;
-
- public function __construct() {
- $this->users = new \Doctrine\Common\Collections\ArrayCollection();
- }
-
- // ...
- }
-
.. code-block:: xml
@@ -1001,30 +652,6 @@ one is bidirectional.
- .. code-block:: yaml
-
- User:
- type: entity
- manyToMany:
- groups:
- targetEntity: Group
- inversedBy: users
- joinTable:
- name: users_groups
- joinColumns:
- user_id:
- referencedColumnName: id
- inverseJoinColumns:
- group_id:
- referencedColumnName: id
-
- Group:
- type: entity
- manyToMany:
- users:
- targetEntity: User
- mappedBy: groups
-
The MySQL schema is exactly the same as for the Many-To-Many
uni-directional case above.
@@ -1172,12 +799,6 @@ As an example, consider this mapping:
#[OneToOne(targetEntity: Shipment::class)]
private Shipment|null $shipment = null;
- .. code-block:: annotation
-
-
@@ -1186,14 +807,6 @@ As an example, consider this mapping:
- .. code-block:: yaml
-
- Product:
- type: entity
- oneToOne:
- shipment:
- targetEntity: Shipment
-
This is essentially the same as the following, more verbose,
mapping:
@@ -1207,16 +820,6 @@ mapping:
#[JoinColumn(name: 'shipment_id', referencedColumnName: 'id')]
private Shipment|null $shipment = null;
- .. code-block:: annotation
-
-
@@ -1227,17 +830,6 @@ mapping:
- .. code-block:: yaml
-
- Product:
- type: entity
- oneToOne:
- shipment:
- targetEntity: Shipment
- joinColumn:
- name: shipment_id
- referencedColumnName: id
-
The @JoinTable definition used for many-to-many mappings has
similar defaults. As an example, consider this mapping:
@@ -1255,20 +847,6 @@ similar defaults. As an example, consider this mapping:
// ...
}
- .. code-block:: annotation
-
-
- */
- private Collection $groups;
- // ...
- }
-
.. code-block:: xml
@@ -1277,14 +855,6 @@ similar defaults. As an example, consider this mapping:
- .. code-block:: yaml
-
- User:
- type: entity
- manyToMany:
- groups:
- targetEntity: Group
-
This is essentially the same as the following, more verbose, mapping:
.. configuration-block::
@@ -1307,25 +877,6 @@ This is essentially the same as the following, more verbose, mapping:
// ...
}
- .. code-block:: annotation
-
-
- */
- private Collection $groups;
- // ...
- }
-
.. code-block:: xml
@@ -1343,22 +894,6 @@ This is essentially the same as the following, more verbose, mapping:
- .. code-block:: yaml
-
- User:
- type: entity
- manyToMany:
- groups:
- targetEntity: Group
- joinTable:
- name: User_Group
- joinColumns:
- User_id:
- referencedColumnName: id
- inverseJoinColumns:
- Group_id:
- referencedColumnName: id
-
In that case, the name of the join table defaults to a combination
of the simple, unqualified class names of the participating
classes, separated by an underscore character. The names of the
@@ -1378,12 +913,6 @@ associations as they will be set based on type. So that:
#[OneToOne]
private Shipment $shipment;
- .. code-block:: annotation
-
-
@@ -1392,13 +921,6 @@ associations as they will be set based on type. So that:
- .. code-block:: yaml
-
- Product:
- type: entity
- oneToOne:
- shipment: ~
-
Is essentially the same as following:
.. configuration-block::
@@ -1431,17 +953,6 @@ Is essentially the same as following:
- .. code-block:: yaml
-
- Product:
- type: entity
- oneToOne:
- shipment:
- targetEntity: Shipment
- joinColumn:
- name: shipment_id
- referencedColumnName: id
-
If you accept these defaults, you can reduce the mapping code to a
minimum.
diff --git a/docs/en/reference/attributes-reference.rst b/docs/en/reference/attributes-reference.rst
index 8709cda6279..d3a1eb04674 100644
--- a/docs/en/reference/attributes-reference.rst
+++ b/docs/en/reference/attributes-reference.rst
@@ -4,8 +4,9 @@ Attributes Reference
PHP 8 adds native support for metadata with its "Attributes" feature.
Doctrine ORM provides support for mapping metadata using PHP attributes as of version 2.9.
-The attributes metadata support is closely modelled after the already existing
-annotation metadata supported since the first version 2.0.
+The attributes metadata support is closely modelled after the already
+existing and now removed annotation metadata supported since the first
+version 2.0.
Index
-----
@@ -310,7 +311,6 @@ Example:
Entity,
ChangeTrackingPolicy("DEFERRED_IMPLICIT"),
ChangeTrackingPolicy("DEFERRED_EXPLICIT"),
- ChangeTrackingPolicy("NOTIFY")
]
class User {}
@@ -485,9 +485,8 @@ used as default.
Optional parameters:
- **strategy**: Set the name of the identifier generation strategy.
- Valid values are ``AUTO``, ``SEQUENCE``, ``IDENTITY``, ``UUID``
- (deprecated), ``CUSTOM`` and ``NONE``.
- If not specified, the default value is ``AUTO``.
+ Valid values are ``AUTO``, ``SEQUENCE``, ``IDENTITY``, ``CUSTOM`` and
+ ``NONE``. If not specified, the default value is ``AUTO``.
Example:
@@ -712,10 +711,6 @@ details of the database join table. If you do not specify
``#[JoinTable]`` on these relations reasonable mapping defaults apply
using the affected table and the column names.
-A notable difference to the annotation metadata support, ``#[JoinColumn]``
-and ``#[InverseJoinColumn]`` can be specified at the property level and are not
-nested within the ``#[JoinTable]`` attribute.
-
Required attribute:
- **name**: Database name of the join-table
@@ -931,7 +926,7 @@ Example:
#[OneToMany(
targetEntity: "Phonenumber",
mappedBy: "user",
- cascade: ["persist", "remove", "merge"],
+ cascade: ["persist", "remove"],
orphanRemoval: true)
]
public $phonenumbers;
diff --git a/docs/en/reference/basic-mapping.rst b/docs/en/reference/basic-mapping.rst
index 0070c271762..55fe0389379 100644
--- a/docs/en/reference/basic-mapping.rst
+++ b/docs/en/reference/basic-mapping.rst
@@ -47,17 +47,14 @@ mapping metadata:
- :doc:`Attributes `
- :doc:`XML `
- :doc:`PHP code `
-- :doc:`Docblock Annotations ` (deprecated and will be removed in ``doctrine/orm`` 3.0)
-- :doc:`YAML ` (deprecated and will be removed in ``doctrine/orm`` 3.0.)
This manual will usually show mapping metadata via attributes, though
-many examples also show the equivalent configuration in annotations,
-YAML and XML.
+many examples also show the equivalent configuration in XML.
.. note::
All metadata drivers perform equally. Once the metadata of a class has been
- read from the source (attributes, annotations, XML, etc.) it is stored in an instance
+ read from the source (attributes, XML, etc.) it is stored in an instance
of the ``Doctrine\ORM\Mapping\ClassMetadata`` class which are
stored in the metadata cache. If you're not using a metadata cache (not
recommended!) then the XML driver is the fastest.
@@ -77,17 +74,6 @@ Marking our ``Message`` class as an entity for Doctrine is straightforward:
// ...
}
- .. code-block:: annotation
-
-
@@ -96,12 +82,6 @@ Marking our ``Message`` class as an entity for Doctrine is straightforward:
- .. code-block:: yaml
-
- Message:
- type: entity
- # ...
-
With no additional information, Doctrine expects the entity to be saved
into a table with the same name as the class in our case ``Message``.
You can change this by configuring information about the table:
@@ -121,21 +101,6 @@ You can change this by configuring information about the table:
// ...
}
- .. code-block:: annotation
-
-
@@ -144,13 +109,6 @@ You can change this by configuring information about the table:
- .. code-block:: yaml
-
- Message:
- type: entity
- table: message
- # ...
-
Now the class ``Message`` will be saved and fetched from the table ``message``.
Property Mapping
@@ -182,23 +140,6 @@ specified, ``string`` is used as the default.
private $postedAt;
}
- .. code-block:: annotation
-
-
@@ -209,19 +150,6 @@ specified, ``string`` is used as the default.
- .. code-block:: yaml
-
- Message:
- type: entity
- fields:
- id:
- type: integer
- text:
- length: 140
- postedAt:
- type: datetime
- column: posted_at
-
When we don't explicitly specify a column name via the ``name`` option, Doctrine
assumes the field name is also the column name. So in this example:
@@ -347,20 +275,6 @@ the field that serves as the identifier with the ``#[Id]`` attribute.
// ...
}
- .. code-block:: annotation
-
-
@@ -372,24 +286,27 @@ the field that serves as the identifier with the ``#[Id]`` attribute.
- .. code-block:: yaml
-
- Message:
- type: entity
- id:
- id:
- type: integer
- generator:
- strategy: AUTO
- fields:
- # fields here
-
In most cases using the automatic generator strategy (``#[GeneratedValue]``) is
what you want, but for backwards-compatibility reasons it might not. It
defaults to the identifier generation mechanism your current database
vendor preferred at the time that strategy was introduced:
``AUTO_INCREMENT`` with MySQL, sequences with PostgreSQL and Oracle and
so on.
+If you are using `doctrine/dbal` 4, we now recommend using ``IDENTITY``
+for PostgreSQL, and ``AUTO`` resolves to it because of that.
+You can stick with ``SEQUENCE`` while still using the ``AUTO``
+strategy, by configuring what it defaults to.
+
+.. code-block:: php
+
+ setIdentityGenerationPreferences([
+ PostgreSQLPlatform::class => ClassMetadata::GENERATOR_TYPE_SEQUENCE,
+ ]);
.. _identifier-generation-strategies:
@@ -418,14 +335,12 @@ Here is the list of possible generation strategies:
generation. This strategy does currently not provide full
portability. Sequences are supported by Oracle, PostgreSql and
SQL Anywhere.
-- ``UUID`` (deprecated): Tells Doctrine to use the built-in Universally
- Unique Identifier generator. This strategy provides full portability.
- ``NONE``: Tells Doctrine that the identifiers are assigned (and
thus generated) by your code. The assignment must take place before
a new entity is passed to ``EntityManager#persist``. NONE is the
same as leaving off the ``#[GeneratedValue]`` entirely.
- ``CUSTOM``: With this option, you can use the ``#[CustomIdGenerator]`` attribute.
- It will allow you to pass a :ref:`class of your own to generate the identifiers. `
+ It will allow you to pass a :ref:`class of your own to generate the identifiers. `
Sequence Generator
^^^^^^^^^^^^^^^^^^
@@ -448,20 +363,6 @@ besides specifying the sequence's name:
// ...
}
- .. code-block:: annotation
-
-
@@ -473,20 +374,6 @@ besides specifying the sequence's name:
- .. code-block:: yaml
-
- Message:
- type: entity
- id:
- id:
- type: integer
- generator:
- strategy: SEQUENCE
- sequenceGenerator:
- sequenceName: message_seq
- allocationSize: 100
- initialValue: 1
-
The initial value specifies at which value the sequence should
start.
diff --git a/docs/en/reference/best-practices.rst b/docs/en/reference/best-practices.rst
index 002c130d5ce..b6f63a61b7b 100644
--- a/docs/en/reference/best-practices.rst
+++ b/docs/en/reference/best-practices.rst
@@ -43,7 +43,7 @@ should use events judiciously.
Use cascades judiciously
------------------------
-Automatic cascades of the persist/remove/merge/etc. operations are
+Automatic cascades of the persist/remove/etc. operations are
very handy but should be used wisely. Do NOT simply add all
cascades to all associations. Think about which cascades actually
do make sense for you for a particular association, given the
diff --git a/docs/en/reference/caching.rst b/docs/en/reference/caching.rst
index 19b30b3d837..1b84fbc93e9 100644
--- a/docs/en/reference/caching.rst
+++ b/docs/en/reference/caching.rst
@@ -109,7 +109,7 @@ Metadata Cache
~~~~~~~~~~~~~~
Your class metadata can be parsed from a few different sources like
-YAML, XML, Attributes, Annotations etc. Instead of parsing this
+XML, Attributes, etc. Instead of parsing this
information on each request we should cache it using one of the cache
drivers.
diff --git a/docs/en/reference/change-tracking-policies.rst b/docs/en/reference/change-tracking-policies.rst
index ea79e1ab050..3d2c2183065 100644
--- a/docs/en/reference/change-tracking-policies.rst
+++ b/docs/en/reference/change-tracking-policies.rst
@@ -5,7 +5,7 @@ Change tracking is the process of determining what has changed in
managed entities since the last time they were synchronized with
the database.
-Doctrine provides 3 different change tracking policies, each having
+Doctrine provides 2 different change tracking policies, each having
its particular advantages and disadvantages. The change tracking
policy can be defined on a per-class basis (or more precisely,
per-hierarchy).
@@ -56,122 +56,3 @@ This policy can be configured as follows:
{
// ...
}
-
-Notify
-~~~~~~
-
-.. note::
-
- The notify change tracking policy is deprecated and will be removed in ORM 3.0.
- (\ `Details `_)
-
-This policy is based on the assumption that the entities notify
-interested listeners of changes to their properties. For that
-purpose, a class that wants to use this policy needs to implement
-the ``NotifyPropertyChanged`` interface from the Doctrine
-namespace. As a guideline, such an implementation can look as
-follows:
-
-.. code-block:: php
-
- _listeners[] = $listener;
- }
- }
-
-Then, in each property setter of this class or derived classes, you
-need to notify all the ``PropertyChangedListener`` instances. As an
-example we add a convenience method on ``MyEntity`` that shows this
-behaviour:
-
-.. code-block:: php
-
- _listeners) {
- foreach ($this->_listeners as $listener) {
- $listener->propertyChanged($this, $propName, $oldValue, $newValue);
- }
- }
- }
-
- public function setData($data): void
- {
- if ($data != $this->data) {
- $this->_onPropertyChanged('data', $this->data, $data);
- $this->data = $data;
- }
- }
- }
-
-You have to invoke ``_onPropertyChanged`` inside every method that
-changes the persistent state of ``MyEntity``.
-
-The check whether the new value is different from the old one is
-not mandatory but recommended. That way you also have full control
-over when you consider a property changed.
-
-If your entity contains an embeddable, you will need to notify
-separately for each property in the embeddable when it changes
-for example:
-
-.. code-block:: php
-
- equals($this->embeddable)) {
- // notice the entityField.embeddableField notation for referencing the property
- $this->_onPropertyChanged('embeddable.prop1', $this->embeddable->getProp1(), $embeddable->getProp1());
- $this->_onPropertyChanged('embeddable.prop2', $this->embeddable->getProp2(), $embeddable->getProp2());
- $this->embeddable = $embeddable;
- }
- }
- }
-
-This would update all the fields of the embeddable, you may wish to
-implement a diff method on your embedded object which returns only
-the changed fields.
-
-The negative point of this policy is obvious: You need implement an
-interface and write some plumbing code. But also note that we tried
-hard to keep this notification functionality abstract. Strictly
-speaking, it has nothing to do with the persistence layer and the
-Doctrine ORM or DBAL. You may find that property notification
-events come in handy in many other scenarios as well. As mentioned
-earlier, the ``Doctrine\Common`` namespace is not that evil and
-consists solely of very small classes and interfaces that have
-almost no external dependencies (none to the DBAL and none to the
-ORM) and that you can easily take with you should you want to swap
-out the persistence layer. This change tracking policy does not
-introduce a dependency on the Doctrine DBAL/ORM or the persistence
-layer.
-
-The positive point and main advantage of this policy is its
-effectiveness. It has the best performance characteristics of the 3
-policies with larger units of work and a flush() operation is very
-cheap when nothing has changed.
diff --git a/docs/en/reference/configuration.rst b/docs/en/reference/configuration.rst
index a65ede69b28..ced4db14058 100644
--- a/docs/en/reference/configuration.rst
+++ b/docs/en/reference/configuration.rst
@@ -60,11 +60,6 @@ access point to ORM functionality provided by Doctrine.
$connection = DriverManager::getConnection($dbParams, $config);
$entityManager = new EntityManager($connection, $config);
-.. note::
-
- The ``ORMSetup`` class has been introduced with ORM 2.12. It's predecessor ``Setup`` is deprecated and will
- be removed in version 3.0.
-
Or if you prefer XML:
.. code-block:: php
@@ -75,23 +70,6 @@ Or if you prefer XML:
$connection = DriverManager::getConnection($dbParams, $config);
$entityManager = new EntityManager($connection, $config);
-Or if you prefer YAML:
-
-.. code-block:: php
-
- createQuery('SELECT partial u.{id, username} FROM CmsUser u');
$users = $query->getResult(); // array of partially loaded CmsUser objects
-You use the partial syntax when joining as well:
+You can use the partial syntax when joining as well:
.. code-block:: php
createQuery('SELECT partial u.{id, username}, partial a.{id, name} FROM CmsUser u JOIN u.articles a');
+ $usersArray = $query->getArrayResult(); // array of partially loaded CmsUser and CmsArticle fields
$users = $query->getResult(); // array of partially loaded CmsUser objects
"NEW" Operator Syntax
@@ -587,7 +588,91 @@ And then use the ``NEW`` DQL keyword :
$query = $em->createQuery('SELECT NEW CustomerDTO(c.name, e.email, a.city, SUM(o.value)) FROM Customer c JOIN c.email e JOIN c.address a JOIN c.orders o GROUP BY c');
$users = $query->getResult(); // array of CustomerDTO
-Note that you can only pass scalar expressions to the constructor.
+You can also nest several DTO :
+
+.. code-block:: php
+
+ createQuery('SELECT NEW CustomerDTO(c.name, e.email, NEW AddressDTO(a.street, a.city, a.zip)) FROM Customer c JOIN c.email e JOIN c.address a');
+ $users = $query->getResult(); // array of CustomerDTO
+
+Note that you can only pass scalar expressions or other Data Transfer Objects to the constructor.
+
+If you use your data transfer objects for multiple queries, and you would rather not have to
+specify arguments that precede the ones you are really interested in, you can use named arguments.
+
+Consider the following DTO, which uses optional arguments:
+
+.. code-block:: php
+
+ createQuery('SELECT NEW NAMED CustomerDTO(a.city, c.name) FROM Customer c JOIN c.address a');
+ $users = $query->getResult(); // array of CustomerDTO
+
+ // CustomerDTO => {name : 'SMITH', email: null, city: 'London', value: null}
+
+ORM will also give precedence to column aliases over column names :
+
+.. code-block:: php
+
+ createQuery('SELECT NEW NAMED CustomerDTO(c.name, CONCAT(a.city, ' ' , a.zip) AS value) FROM Customer c JOIN c.address a');
+ $users = $query->getResult(); // array of CustomerDTO
+
+ // CustomerDTO => {name : 'DOE', email: null, city: null, value: 'New York 10011'}
+
+To define a custom name for a DTO constructor argument, you can either alias the column with the ``AS`` keyword.
+
+The ``NAMED`` keyword must precede all DTO you want to instantiate :
+
+.. code-block:: php
+
+ createQuery('SELECT NEW NAMED CustomerDTO(c.name, NEW NAMED AddressDTO(a.street, a.city, a.zip) AS address) FROM Customer c JOIN c.address a');
+ $users = $query->getResult(); // array of CustomerDTO
+
+ // CustomerDTO => {name : 'DOE', email: null, city: null, value: 'New York 10011'}
+
+If two arguments have the same name, a ``DuplicateFieldException`` is thrown.
+If a field cannot be matched with a property name, a ``NoMatchingPropertyException`` is thrown. This typically happens when using functions without aliasing them.
Using INDEX BY
~~~~~~~~~~~~~~
@@ -1516,8 +1601,8 @@ Identifiers
/* Alias Identification declaration (the "u" of "FROM User u") */
AliasIdentificationVariable :: = identifier
- /* identifier that must be a class name (the "User" of "FROM User u"), possibly as a fully qualified class name or namespace-aliased */
- AbstractSchemaName ::= fully_qualified_name | aliased_name | identifier
+ /* identifier that must be a class name (the "User" of "FROM User u"), possibly as a fully qualified class name */
+ AbstractSchemaName ::= fully_qualified_name | identifier
/* Alias ResultVariable declaration (the "total" of "COUNT(*) AS total") */
AliasResultVariable = identifier
@@ -1617,7 +1702,7 @@ Select Expressions
PartialObjectExpression ::= "PARTIAL" IdentificationVariable "." PartialFieldSet
PartialFieldSet ::= "{" SimpleStateField {"," SimpleStateField}* "}"
NewObjectExpression ::= "NEW" AbstractSchemaName "(" NewObjectArg {"," NewObjectArg}* ")"
- NewObjectArg ::= ScalarExpression | "(" Subselect ")"
+ NewObjectArg ::= (ScalarExpression | "(" Subselect ")" | NewObjectExpression) ["AS" AliasResultVariable]
Conditional Expressions
~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/en/reference/events.rst b/docs/en/reference/events.rst
index dbde6d19df2..4211a198577 100644
--- a/docs/en/reference/events.rst
+++ b/docs/en/reference/events.rst
@@ -260,40 +260,6 @@ specific to a particular entity class's lifecycle.
$this->value = 'changed from preUpdate callback!';
}
}
- .. code-block:: annotation
-
- createdAt = date('Y-m-d H:i:s');
- }
-
- /** @PrePersist */
- public function doOtherStuffOnPrePersist()
- {
- $this->value = 'changed from prePersist callback!';
- }
-
- /** @PreUpdate */
- public function doStuffOnPreUpdate(PreUpdateEventArgs $eventArgs)
- {
- $this->value = 'changed from preUpdate callback!';
- }
- }
.. code-block:: xml
@@ -311,17 +277,6 @@ specific to a particular entity class's lifecycle.
- .. code-block:: yaml
-
- User:
- type: entity
- fields:
- # ...
- value:
- type: string(255)
- lifecycleCallbacks:
- prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersist ]
- preUpdate: [ doStuffOnPreUpdate ]
Lifecycle Callbacks Event Argument
----------------------------------
@@ -794,16 +749,6 @@ An entity listener is a lifecycle listener class used for an entity.
{
// ....
}
- .. code-block:: annotation
-
-
@@ -814,13 +759,6 @@ An entity listener is a lifecycle listener class used for an entity.
- .. code-block:: yaml
-
- MyProject\Entity\User:
- type: entity
- entityListeners:
- UserListener:
- # ....
.. _reference-entity-listeners:
@@ -893,45 +831,6 @@ you need to map the listener method using the event type mapping:
public function postLoadHandler(User $user, PostLoadEventArgs $event): void { // ... }
}
- .. code-block:: annotation
-
-
@@ -954,24 +853,6 @@ you need to map the listener method using the event type mapping:
- .. code-block:: yaml
-
- MyProject\Entity\User:
- type: entity
- entityListeners:
- UserListener:
- preFlush: [preFlushHandler]
- postLoad: [postLoadHandler]
-
- postPersist: [postPersistHandler]
- prePersist: [prePersistHandler]
-
- postUpdate: [postUpdateHandler]
- preUpdate: [preUpdateHandler]
-
- postRemove: [postRemoveHandler]
- preRemove: [preRemoveHandler]
- # ....
.. note::
@@ -994,7 +875,8 @@ Specifying an entity listener instance :
// User.php
- /** @Entity @EntityListeners({"UserListener"}) */
+ #[Entity]
+ #[EntityListeners(["UserListener"])
class User
{
// ....
@@ -1052,7 +934,7 @@ Load ClassMetadata Event
``loadClassMetadata`` - The ``loadClassMetadata`` event occurs after the
mapping metadata for a class has been loaded from a mapping source
-(attributes/annotations/xml/yaml) in to a ``Doctrine\ORM\Mapping\ClassMetadata`` instance.
+(attributes/xml) in to a ``Doctrine\ORM\Mapping\ClassMetadata`` instance.
You can hook in to this process and manipulate the instance.
This event is not a lifecycle callback.
diff --git a/docs/en/reference/inheritance-mapping.rst b/docs/en/reference/inheritance-mapping.rst
index 448c9dd401b..f06341810c0 100644
--- a/docs/en/reference/inheritance-mapping.rst
+++ b/docs/en/reference/inheritance-mapping.rst
@@ -16,7 +16,7 @@ is common to multiple entity classes.
Mapped superclasses, just as regular, non-mapped classes, can
appear in the middle of an otherwise mapped inheritance hierarchy
(through Single Table Inheritance or Class Table Inheritance). They
-are not query-able, and need not have an ``#[Id]`` property.
+are not query-able, and do not require an ``#[Id]`` property.
No database table will be created for a mapped superclass itself,
only for entity classes inheriting from it. That implies that a
@@ -208,44 +208,6 @@ Example:
// ...
}
- .. code-block:: annotation
-
-
- */
- protected Collection $groups;
-
- /**
- * @ManyToOne(targetEntity="Address")
- * @JoinColumn(name="address_id", referencedColumnName="id")
- */
- protected Address|null $address = null;
- }
-
- // admin mapping
- namespace MyProject\Model;
- /**
- * @Entity
- * @AssociationOverrides({
- * @AssociationOverride(name="groups",
- * joinTable=@JoinTable(
- * name="users_admingroups",
- * joinColumns=@JoinColumn(name="adminuser_id"),
- * inverseJoinColumns=@JoinColumn(name="admingroup_id")
- * )
- * ),
- * @AssociationOverride(name="address",
- * joinColumns=@JoinColumn(
- * name="adminaddress_id", referencedColumnName="id"
- * )
- * )
- * })
- */
- class Admin extends User
- {
- }
-
.. code-block:: xml
@@ -500,7 +410,6 @@ Example:
-
@@ -537,51 +446,6 @@ Example:
- .. code-block:: yaml
-
- # user mapping
- MyProject\Model\User:
- type: mappedSuperclass
- # other fields mapping
- manyToOne:
- address:
- targetEntity: Address
- joinColumn:
- name: address_id
- referencedColumnName: id
- cascade: [ persist, merge ]
- manyToMany:
- groups:
- targetEntity: Group
- joinTable:
- name: users_groups
- joinColumns:
- user_id:
- referencedColumnName: id
- inverseJoinColumns:
- group_id:
- referencedColumnName: id
- cascade: [ persist, merge, detach ]
-
- # admin mapping
- MyProject\Model\Admin:
- type: entity
- associationOverride:
- address:
- joinColumn:
- adminaddress_id:
- name: adminaddress_id
- referencedColumnName: id
- groups:
- joinTable:
- name: users_admingroups
- joinColumns:
- adminuser_id:
- referencedColumnName: id
- inverseJoinColumns:
- admingroup_id:
- referencedColumnName: id
-
Things to note:
@@ -645,51 +509,6 @@ Could be used by an entity that extends a mapped superclass to override a field
{
}
- .. code-block:: annotation
-
-
@@ -702,7 +521,6 @@ Could be used by an entity that extends a mapped superclass to override a field
-
@@ -723,42 +541,6 @@ Could be used by an entity that extends a mapped superclass to override a field
- .. code-block:: yaml
-
- # user mapping
- MyProject\Model\User:
- type: mappedSuperclass
- id:
- id:
- type: integer
- column: user_id
- length: 150
- generator:
- strategy: AUTO
- fields:
- name:
- type: string
- column: user_name
- length: 250
- nullable: true
- unique: false
- #other fields mapping
-
-
- # guest mapping
- MyProject\Model\Guest:
- type: entity
- attributeOverride:
- id:
- column: guest_id
- type: integer
- length: 140
- name:
- column: guest_name
- type: string
- length: 240
- nullable: false
- unique: true
Things to note:
diff --git a/docs/en/reference/limitations-and-known-issues.rst b/docs/en/reference/limitations-and-known-issues.rst
index 09b6e0ee578..d261355459e 100644
--- a/docs/en/reference/limitations-and-known-issues.rst
+++ b/docs/en/reference/limitations-and-known-issues.rst
@@ -65,15 +65,6 @@ Where the ``attribute_name`` column contains the key and
The feature request for persistence of primitive value arrays
`is described in the DDC-298 ticket `_.
-Cascade Merge with Bi-directional Associations
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-There are two bugs now that concern the use of cascade merge in combination with bi-directional associations.
-Make sure to study the behavior of cascade merge if you are using it:
-
-- `DDC-875 `_ Merge can sometimes add the same entity twice into a collection
-- `DDC-763 `_ Cascade merge on associated entities can insert too many rows through "Persistence by Reachability"
-
Custom Persisters
~~~~~~~~~~~~~~~~~
diff --git a/docs/en/reference/metadata-drivers.rst b/docs/en/reference/metadata-drivers.rst
index a3718cbc838..6c3d62d8596 100644
--- a/docs/en/reference/metadata-drivers.rst
+++ b/docs/en/reference/metadata-drivers.rst
@@ -16,13 +16,6 @@ metadata:
- **Attributes** (AttributeDriver)
- **PHP Code in files or static functions** (PhpDriver)
-There are also two deprecated ways to do this:
-
-- **Class DocBlock Annotations** (AnnotationDriver)
-- **YAML files** (YamlDriver)
-
-They will be removed in 3.0, make sure to avoid them.
-
Something important to note about the above drivers is they are all
an intermediate step to the same end result. The mapping
information is populated to ``Doctrine\ORM\Mapping\ClassMetadata``
@@ -44,11 +37,7 @@ an entity.
$em->getConfiguration()->setMetadataCacheImpl(new ApcuCache());
-If you want to use one of the included core metadata drivers you need to
-configure it. If you pick the annotation driver despite it being
-deprecated, you will additionally need to install
-``doctrine/annotations``. All the drivers are in the
-``Doctrine\ORM\Mapping\Driver`` namespace:
+All the drivers are in the ``Doctrine\ORM\Mapping\Driver`` namespace:
.. code-block:: php
diff --git a/docs/en/reference/namingstrategy.rst b/docs/en/reference/namingstrategy.rst
index 53d75465c2b..9ea3e772f33 100644
--- a/docs/en/reference/namingstrategy.rst
+++ b/docs/en/reference/namingstrategy.rst
@@ -110,28 +110,28 @@ You need to create a class which implements ``Doctrine\ORM\Mapping\NamingStrateg
referenceColumnName();
}
- public function joinTableName($sourceEntity, $targetEntity, $propertyName = null)
+ public function joinTableName(string $sourceEntity, string $targetEntity, string $propertyName): string
{
return strtolower($this->classToTableName($sourceEntity) . '_' .
$this->classToTableName($targetEntity));
}
- public function joinKeyColumnName($entityName, $referencedColumnName = null)
+ public function joinKeyColumnName(string $entityName, ?string $referencedColumnName): string
{
return strtolower($this->classToTableName($entityName) . '_' .
($referencedColumnName ?: $this->referenceColumnName()));
diff --git a/docs/en/reference/native-sql.rst b/docs/en/reference/native-sql.rst
index 97d92dd3861..62aaf11ab47 100644
--- a/docs/en/reference/native-sql.rst
+++ b/docs/en/reference/native-sql.rst
@@ -465,477 +465,3 @@ above would result in partial objects if any objects in the result
are actually a subtype of User. When using DQL, Doctrine
automatically includes the necessary joins for this mapping
strategy but with native SQL it is your responsibility.
-
-Named Native Query
-------------------
-
-.. note::
-
- Named Native Queries are deprecated as of version 2.9 and will be removed in ORM 3.0
-
-You can also map a native query using a named native query mapping.
-
-To achieve that, you must describe the SQL resultset structure
-using named native query (and sql resultset mappings if is a several resultset mappings).
-
-Like named query, a named native query can be defined at class level or in a XML or YAML file.
-
-
-A resultSetMapping parameter is defined in @NamedNativeQuery,
-it represents the name of a defined @SqlResultSetMapping.
-
-.. configuration-block::
-
- .. code-block:: php
-
-
-
-
-
- SELECT u.id AS u_id, u.name AS u_name, u.status AS u_status, a.id AS a_id, a.zip AS a_zip, a.country AS a_country, COUNT(p.phonenumber) AS numphones FROM users u INNER JOIN addresses a ON u.id = a.user_id INNER JOIN phonenumbers p ON u.id = p.user_id GROUP BY u.id, u.name, u.status, u.username, a.id, a.zip, a.country ORDER BY u.username
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- .. code-block:: yaml
-
- MyProject\Model\User:
- type: entity
- namedNativeQueries:
- fetchMultipleJoinsEntityResults:
- name: fetchMultipleJoinsEntityResults
- resultSetMapping: mappingMultipleJoinsEntityResults
- query: SELECT u.id AS u_id, u.name AS u_name, u.status AS u_status, a.id AS a_id, a.zip AS a_zip, a.country AS a_country, COUNT(p.phonenumber) AS numphones FROM users u INNER JOIN addresses a ON u.id = a.user_id INNER JOIN phonenumbers p ON u.id = p.user_id GROUP BY u.id, u.name, u.status, u.username, a.id, a.zip, a.country ORDER BY u.username
- sqlResultSetMappings:
- mappingMultipleJoinsEntityResults:
- name: mappingMultipleJoinsEntityResults
- columnResult:
- 0:
- name: numphones
- entityResult:
- 0:
- entityClass: __CLASS__
- fieldResult:
- 0:
- name: id
- column: u_id
- 1:
- name: name
- column: u_name
- 2:
- name: status
- column: u_status
- 1:
- entityClass: Address
- fieldResult:
- 0:
- name: id
- column: a_id
- 1:
- name: zip
- column: a_zip
- 2:
- name: country
- column: a_country
-
-
-Things to note:
- - The resultset mapping declares the entities retrieved by this native query.
- - Each field of the entity is bound to a SQL alias (or column name).
- - All fields of the entity including the ones of subclasses
- and the foreign key columns of related entities have to be present in the SQL query.
- - Field definitions are optional provided that they map to the same
- column name as the one declared on the class property.
- - ``__CLASS__`` is an alias for the mapped class
-
-
-In the above example,
-the ``fetchJoinedAddress`` named query use the joinMapping result set mapping.
-This mapping returns 2 entities, User and Address, each property is declared and associated to a column name,
-actually the column name retrieved by the query.
-
-Let's now see an implicit declaration of the property / column.
-
-.. configuration-block::
-
- .. code-block:: php
-
-
-
-
-
- SELECT * FROM addresses
-
-
-
-
-
-
-
-
-
- .. code-block:: yaml
-
- MyProject\Model\Address:
- type: entity
- namedNativeQueries:
- findAll:
- resultSetMapping: mappingFindAll
- query: SELECT * FROM addresses
- sqlResultSetMappings:
- mappingFindAll:
- name: mappingFindAll
- entityResult:
- address:
- entityClass: Address
-
-
-In this example, we only describe the entity member of the result set mapping.
-The property / column mappings is done using the entity mapping values.
-In this case the model property is bound to the model_txt column.
-If the association to a related entity involve a composite primary key,
-a @FieldResult element should be used for each foreign key column.
-The @FieldResult name is composed of the property name for the relationship,
-followed by a dot ("."), followed by the name or the field or property of the primary key.
-
-
-.. configuration-block::
-
- .. code-block:: php
-
-
-
-
-
- SELECT u.id, u.name, u.status, a.id AS a_id, a.country AS a_country, a.zip AS a_zip, a.city AS a_city FROM users u INNER JOIN addresses a ON u.id = a.user_id WHERE u.username = ?
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- .. code-block:: yaml
-
- MyProject\Model\User:
- type: entity
- namedNativeQueries:
- fetchJoinedAddress:
- name: fetchJoinedAddress
- resultSetMapping: mappingJoinedAddress
- query: SELECT u.id, u.name, u.status, a.id AS a_id, a.country AS a_country, a.zip AS a_zip, a.city AS a_city FROM users u INNER JOIN addresses a ON u.id = a.user_id WHERE u.username = ?
- sqlResultSetMappings:
- mappingJoinedAddress:
- entityResult:
- 0:
- entityClass: __CLASS__
- fieldResult:
- 0:
- name: id
- 1:
- name: name
- 2:
- name: status
- 3:
- name: address.id
- column: a_id
- 4:
- name: address.zip
- column: a_zip
- 5:
- name: address.city
- column: a_city
- 6:
- name: address.country
- column: a_country
-
-
-
-If you retrieve a single entity and if you use the default mapping,
-you can use the resultClass attribute instead of resultSetMapping:
-
-.. configuration-block::
-
- .. code-block:: php
-
-
-
-
-
- SELECT * FROM addresses WHERE id = ?
-
-
-
-
- .. code-block:: yaml
-
- MyProject\Model\Address:
- type: entity
- namedNativeQueries:
- findAll:
- name: findAll
- resultClass: Address
- query: SELECT * FROM addresses
-
-
-In some of your native queries, you'll have to return scalar values,
-for example when building report queries.
-You can map them in the @SqlResultsetMapping through @ColumnResult.
-You actually can even mix, entities and scalar returns in the same native query (this is probably not that common though).
-
-.. configuration-block::
-
- .. code-block:: php
-
-
-
-
- SELECT COUNT(*) AS count FROM addresses
-
-
-
-
-
-
-
-
- .. code-block:: yaml
-
- MyProject\Model\Address:
- type: entity
- namedNativeQueries:
- count:
- name: count
- resultSetMapping: mappingCount
- query: SELECT COUNT(*) AS count FROM addresses
- sqlResultSetMappings:
- mappingCount:
- name: mappingCount
- columnResult:
- count:
- name: count
diff --git a/docs/en/reference/partial-hydration.rst b/docs/en/reference/partial-hydration.rst
new file mode 100644
index 00000000000..fda14b98efa
--- /dev/null
+++ b/docs/en/reference/partial-hydration.rst
@@ -0,0 +1,15 @@
+Partial Hydration
+=================
+
+Partial hydration of entities is allowed in the array hydrator, when
+only a subset of the fields of an entity are loaded from the database
+and the nested results are still created based on the entity relationship structure.
+
+.. code-block:: php
+
+ createQuery("SELECT PARTIAL u.{id,name}, partial a.{id,street} FROM MyApp\Domain\User u JOIN u.addresses a")
+ ->getArrayResult();
+
+This is a useful optimization when you are not interested in all fields of an entity
+for performance reasons, for example in use-cases for exporting or rendering lots of data.
diff --git a/docs/en/reference/partial-objects.rst b/docs/en/reference/partial-objects.rst
index 51f173adf6c..3123c083f3f 100644
--- a/docs/en/reference/partial-objects.rst
+++ b/docs/en/reference/partial-objects.rst
@@ -1,19 +1,11 @@
Partial Objects
===============
-
-.. note::
-
- Creating Partial Objects through DQL is deprecated and
- will be removed in the future, use data transfer object
- support in DQL instead. (\ `Details
- `_)
-
A partial object is an object whose state is not fully initialized
after being reconstituted from the database and that is
disconnected from the rest of its data. The following section will
describe why partial objects are problematic and what the approach
-of Doctrine2 to this problem is.
+of Doctrine to this problem is.
.. note::
@@ -94,5 +86,3 @@ When should I force partial objects?
Mainly for optimization purposes, but be careful of premature
optimization as partial objects lead to potentially more fragile
code.
-
-
diff --git a/docs/en/reference/php-mapping.rst b/docs/en/reference/php-mapping.rst
index 73ebc332165..b9545238cb3 100644
--- a/docs/en/reference/php-mapping.rst
+++ b/docs/en/reference/php-mapping.rst
@@ -1,97 +1,20 @@
PHP Mapping
===========
-Doctrine ORM also allows you to provide the ORM metadata in the form
-of plain PHP code using the ``ClassMetadata`` API. You can write
-the code in PHP files or inside of a static function named
-``loadMetadata($class)`` on the entity class itself.
-
-PHP Files
----------
-
-.. note::
-
- PHPDriver is deprecated and will be removed in 3.0, use StaticPHPDriver
- instead.
-
-If you wish to write your mapping information inside PHP files that
-are named after the entity and included to populate the metadata
-for an entity you can do so by using the ``PHPDriver``:
-
-.. code-block:: php
-
- getConfiguration()->setMetadataDriverImpl($driver);
-
-Now imagine we had an entity named ``Entities\User`` and we wanted
-to write a mapping file for it using the above configured
-``PHPDriver`` instance:
-
-.. code-block:: php
-
- mapField(array(
- 'id' => true,
- 'fieldName' => 'id',
- 'type' => 'integer'
- ));
-
- $metadata->mapField(array(
- 'fieldName' => 'username',
- 'type' => 'string',
- 'options' => array(
- 'fixed' => true,
- 'comment' => "User's login name"
- )
- ));
-
- $metadata->mapField(array(
- 'fieldName' => 'login_count',
- 'type' => 'integer',
- 'nullable' => false,
- 'options' => array(
- 'unsigned' => true,
- 'default' => 0
- )
- ));
-
-Now we can easily retrieve the populated ``ClassMetadata`` instance
-where the ``PHPDriver`` includes the file and the
-``ClassMetadataFactory`` caches it for later retrieval:
-
-.. code-block:: php
-
- getClassMetadata('Entities\User');
- // or
- $class = $em->getMetadataFactory()->getMetadataFor('Entities\User');
+Doctrine ORM also allows you to provide the ORM metadata in the form of plain
+PHP code using the ``ClassMetadata`` API. You can write the code in inside of a
+static function named ``loadMetadata($class)`` on the entity class itself.
Static Function
---------------
-In addition to the PHP files you can also specify your mapping
-information inside of a static function defined on the entity class
-itself. This is useful for cases where you want to keep your entity
-and mapping information together but don't want to use attributes or
-annotations. For this you just need to use the ``StaticPHPDriver``:
+In addition to other drivers using configuration languages you can also
+programatically specify your mapping information inside of a static function
+defined on the entity class itself.
+
+This is useful for cases where you want to keep your entity and mapping
+information together but don't want to use attributes. For this you just
+need to use the ``StaticPHPDriver``:
.. code-block:: php
@@ -150,7 +73,7 @@ To ease the use of the ClassMetadata API (which is very raw) there is a ``ClassM
public static function loadMetadata(ClassMetadata $metadata)
{
$builder = new ClassMetadataBuilder($metadata);
- $builder->createField('id', 'integer')->isPrimaryKey()->generatedValue()->build();
+ $builder->createField('id', 'integer')->makePrimaryKey()->generatedValue()->build();
$builder->addField('username', 'string');
}
}
@@ -164,13 +87,11 @@ The API of the ClassMetadataBuilder has the following methods with a fluent inte
- ``setTable($name)``
- ``addIndex(array $columns, $indexName)``
- ``addUniqueConstraint(array $columns, $constraintName)``
-- ``addNamedQuery($name, $dqlQuery)``
- ``setJoinedTableInheritance()``
- ``setSingleTableInheritance()``
- ``setDiscriminatorColumn($name, $type = 'string', $length = 255, $columnDefinition = null, $enumType = null, $options = [])``
- ``addDiscriminatorMapClass($name, $class)``
- ``setChangeTrackingPolicyDeferredExplicit()``
-- ``setChangeTrackingPolicyNotify()``
- ``addLifecycleEvent($methodName, $event)``
- ``addManyToOne($name, $targetEntity, $inversedBy = null)``
- ``addInverseOneToOne($name, $targetEntity, $mappedBy)``
@@ -272,7 +193,6 @@ Inheritance Getters
- ``isInheritanceTypeNone()``
- ``isInheritanceTypeJoined()``
- ``isInheritanceTypeSingleTable()``
-- ``isInheritanceTypeTablePerClass()``
- ``isInheritedField($fieldName)``
- ``isInheritedAssociation($fieldName)``
@@ -282,7 +202,6 @@ Change Tracking Getters
- ``isChangeTrackingDeferredExplicit()``
- ``isChangeTrackingDeferredImplicit()``
-- ``isChangeTrackingNotify()``
Field & Association Getters
~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/en/reference/query-builder.rst b/docs/en/reference/query-builder.rst
index 3070cc234df..41ef31420ae 100644
--- a/docs/en/reference/query-builder.rst
+++ b/docs/en/reference/query-builder.rst
@@ -611,3 +611,21 @@ same query of example 6 written using
->add('from', new Expr\From('User', 'u'))
->add('where', new Expr\Comparison('u.id', '=', '?1'))
->add('orderBy', new Expr\OrderBy('u.name', 'ASC'));
+
+Binding Parameters to Placeholders
+----------------------------------
+
+It is often not necessary to know about the exact placeholder names when
+building a query. You can use a helper method to bind a value to a placeholder
+and directly use that placeholder in your query as a return value:
+
+.. code-block:: php
+
+ select('u')
+ ->from('User', 'u')
+ ->where('u.email = ' . $qb->createNamedParameter($userInputEmail))
+ ;
+ // SELECT u FROM User u WHERE email = :dcValue1
diff --git a/docs/en/reference/second-level-cache.rst b/docs/en/reference/second-level-cache.rst
index cf5cb37d4fa..829db16101f 100644
--- a/docs/en/reference/second-level-cache.rst
+++ b/docs/en/reference/second-level-cache.rst
@@ -295,30 +295,6 @@ level cache region.
// other properties and methods
}
- .. code-block:: annotation
-
-
@@ -335,24 +311,6 @@ level cache region.
- .. code-block:: yaml
-
- Country:
- type: entity
- cache:
- usage: READ_ONLY
- region: my_entity_region
- id:
- id:
- type: integer
- id: true
- generator:
- strategy: IDENTITY
- fields:
- name:
- type: string
-
-
Association cache definition
----------------------------
The most common use case is to cache entities. But we can also cache relationships.
@@ -389,44 +347,6 @@ It caches the primary keys of association and cache each element will be cached
// other properties and methods
}
- .. code-block:: annotation
-
-
- */
- protected Collection $cities;
-
- // other properties and methods
- }
-
.. code-block:: xml
@@ -458,38 +378,6 @@ It caches the primary keys of association and cache each element will be cached
- .. code-block:: yaml
-
- State:
- type: entity
- cache:
- usage: NONSTRICT_READ_WRITE
- id:
- id:
- type: integer
- id: true
- generator:
- strategy: IDENTITY
- fields:
- name:
- type: string
-
- manyToOne:
- state:
- targetEntity: Country
- joinColumns:
- country_id:
- referencedColumnName: id
- cache:
- usage: NONSTRICT_READ_WRITE
-
- oneToMany:
- cities:
- targetEntity:City
- mappedBy: state
- cache:
- usage: NONSTRICT_READ_WRITE
-
.. note::
for this to work, the target entity must also be marked as cacheable.
diff --git a/docs/en/reference/tools.rst b/docs/en/reference/tools.rst
index 5c290ccebf9..a438fb2789b 100644
--- a/docs/en/reference/tools.rst
+++ b/docs/en/reference/tools.rst
@@ -83,18 +83,8 @@ The following Commands are currently available:
cache drivers.
- ``orm:clear-cache:result`` Clear result cache of the various
cache drivers.
-- ``orm:convert-d1-schema`` Converts Doctrine 1.X schema into a
- Doctrine 2.X schema.
-- ``orm:convert-mapping`` Convert mapping information between
- supported formats.
-- ``orm:ensure-production-settings`` Verify that Doctrine is
- properly configured for a production environment.
-- ``orm:generate-entities`` Generate entity classes and method
- stubs from your mapping information.
- ``orm:generate-proxies`` Generates proxy classes for entity
classes.
-- ``orm:generate-repositories`` Generate repository classes from
- your mapping information.
- ``orm:run-dql`` Executes arbitrary DQL directly from the command
line.
- ``orm:schema-tool:create`` Processes the schema and either
@@ -107,14 +97,10 @@ The following Commands are currently available:
update the database schema of EntityManager Storage Connection or
generate the SQL output.
-For these commands are also available aliases:
+The following alias is defined:
-- ``orm:convert:d1-schema`` is alias for ``orm:convert-d1-schema``.
-- ``orm:convert:mapping`` is alias for ``orm:convert-mapping``.
-- ``orm:generate:entities`` is alias for ``orm:generate-entities``.
- ``orm:generate:proxies`` is alias for ``orm:generate-proxies``.
-- ``orm:generate:repositories`` is alias for ``orm:generate-repositories``.
.. note::
@@ -225,163 +211,6 @@ will output the SQL for the ran operation.
$ php bin/doctrine orm:schema-tool:create --dump-sql
-Entity Generation
------------------
-
-Generate entity classes and method stubs from your mapping information.
-
-.. code-block:: php
-
- $ php bin/doctrine orm:generate-entities
- $ php bin/doctrine orm:generate-entities --update-entities
- $ php bin/doctrine orm:generate-entities --regenerate-entities
-
-This command is not suited for constant usage. It is a little helper and does
-not support all the mapping edge cases very well. You still have to put work
-in your entities after using this command.
-
-It is possible to use the EntityGenerator on code that you have already written. It will
-not be lost. The EntityGenerator will only append new code to your
-file and will not delete the old code. However this approach may still be prone
-to error and we suggest you use code repositories such as GIT or SVN to make
-backups of your code.
-
-It makes sense to generate the entity code if you are using entities as Data
-Access Objects only and don't put much additional logic on them. If you are
-however putting much more logic on the entities you should refrain from using
-the entity-generator and code your entities manually.
-
-.. note::
-
- Even if you specified Inheritance options in your
- XML or YAML Mapping files the generator cannot generate the base and
- child classes for you correctly, because it doesn't know which
- class is supposed to extend which. You have to adjust the entity
- code manually for inheritance to work!
-
-
-Convert Mapping Information
----------------------------
-
-Convert mapping information between supported formats.
-
-This is an **execute one-time** command. It should not be necessary for
-you to call this method multiple times, especially when using the ``--from-database``
-flag.
-
-Converting an existing database schema into mapping files only solves about 70-80%
-of the necessary mapping information. Additionally the detection from an existing
-database cannot detect inverse associations, inheritance types,
-entities with foreign keys as primary keys and many of the
-semantical operations on associations such as cascade.
-
-.. note::
-
- There is no need to convert YAML or XML mapping files to annotations
- every time you make changes. All mapping drivers are first class citizens
- in Doctrine 2 and can be used as runtime mapping for the ORM. See the
- docs on XML and YAML Mapping for an example how to register this metadata
- drivers as primary mapping source.
-
-To convert some mapping information between the various supported
-formats you can use the ``ClassMetadataExporter`` to get exporter
-instances for the different formats:
-
-.. code-block:: php
-
- getExporter('yml', '/path/to/export/yml');
-
-Now you can export some ``ClassMetadata`` instances:
-
-.. code-block:: php
-
- getClassMetadata('Entities\User'),
- $em->getClassMetadata('Entities\Profile')
- );
- $exporter->setMetadata($classes);
- $exporter->export();
-
-This functionality is also available from the command line to
-convert your loaded mapping information to another format. The
-``orm:convert-mapping`` command accepts two arguments, the type to
-convert to and the path to generate it:
-
-.. code-block:: php
-
- $ php bin/doctrine orm:convert-mapping xml /path/to/mapping-path-converted-to-xml
-
-Reverse Engineering
--------------------
-
-You can use the ``DatabaseDriver`` to reverse engineer a database to an
-array of ``ClassMetadata`` instances and generate YAML, XML, etc. from
-them.
-
-.. note::
-
- Reverse Engineering is a **one-time** process that can get you started with a project.
- Converting an existing database schema into mapping files only detects about 70-80%
- of the necessary mapping information. Additionally the detection from an existing
- database cannot detect inverse associations, inheritance types,
- entities with foreign keys as primary keys and many of the
- semantical operations on associations such as cascade.
-
-First you need to retrieve the metadata instances with the
-``DatabaseDriver``:
-
-.. code-block:: php
-
- getConfiguration()->setMetadataDriverImpl(
- new \Doctrine\ORM\Mapping\Driver\DatabaseDriver(
- $em->getConnection()->getSchemaManager()
- )
- );
-
- $cmf = new \Doctrine\ORM\Tools\DisconnectedClassMetadataFactory();
- $cmf->setEntityManager($em);
- $metadata = $cmf->getAllMetadata();
-
-Now you can get an exporter instance and export the loaded metadata
-to yml:
-
-.. code-block:: php
-
- getExporter('yml', '/path/to/export/yml');
- $exporter->setMetadata($metadata);
- $exporter->export();
-
-You can also reverse engineer a database using the
-``orm:convert-mapping`` command:
-
-.. code-block:: php
-
- $ php bin/doctrine orm:convert-mapping --from-database yml /path/to/mapping-path-converted-to-yml
-
-.. note::
-
- Reverse Engineering is not always working perfectly
- depending on special cases. It will only detect Many-To-One
- relations (even if they are One-To-One) and will try to create
- entities from Many-To-Many tables. It also has problems with naming
- of foreign keys that have multiple column names. Any Reverse
- Engineered Database-Schema needs considerable manual work to become
- a useful domain model.
-
-
Runtime vs Development Mapping Validation
-----------------------------------------
diff --git a/docs/en/reference/transactions-and-concurrency.rst b/docs/en/reference/transactions-and-concurrency.rst
index afcbb216bce..485b73e7251 100644
--- a/docs/en/reference/transactions-and-concurrency.rst
+++ b/docs/en/reference/transactions-and-concurrency.rst
@@ -202,17 +202,6 @@ example we'll use an integer.
// ...
}
- .. code-block:: annotation
-
-
@@ -221,15 +210,6 @@ example we'll use an integer.
- .. code-block:: yaml
-
- User:
- type: entity
- fields:
- version:
- type: integer
- version: true
-
Alternatively a datetime type can be used (which maps to a SQL
timestamp or datetime):
@@ -246,17 +226,6 @@ timestamp or datetime):
// ...
}
- .. code-block:: annotation
-
-
@@ -265,15 +234,6 @@ timestamp or datetime):
- .. code-block:: yaml
-
- User:
- type: entity
- fields:
- version:
- type: datetime
- version: true
-
Version numbers (not timestamps) should however be preferred as
they can not potentially conflict in a highly concurrent
environment, unlike timestamps where this is a possibility,
diff --git a/docs/en/reference/typedfieldmapper.rst b/docs/en/reference/typedfieldmapper.rst
index 982d0a50eda..47a703cebe6 100644
--- a/docs/en/reference/typedfieldmapper.rst
+++ b/docs/en/reference/typedfieldmapper.rst
@@ -47,21 +47,6 @@ Then, an entity using the ``CustomIdObject`` typed field will be correctly assig
// ...
}
- .. code-block:: annotation
-
-
@@ -176,4 +161,4 @@ You need to create a class which implements ``Doctrine\ORM\Mapping\TypedFieldMap
Note that this case checks whether the mapping is already assigned, and if yes, it skips it. This is up to your
implementation. You can make a "greedy" mapper which will always override the mapping with its own type, or one
- that behaves like the ``DefaultTypedFieldMapper`` and does not modify the type once its set prior in the chain.
\ No newline at end of file
+ that behaves like the ``DefaultTypedFieldMapper`` and does not modify the type once its set prior in the chain.
diff --git a/docs/en/reference/unitofwork.rst b/docs/en/reference/unitofwork.rst
index 9c18fba0da7..94831ff4f36 100644
--- a/docs/en/reference/unitofwork.rst
+++ b/docs/en/reference/unitofwork.rst
@@ -129,16 +129,10 @@ optimize the performance of the Flush Operation:
- Temporarily mark entities as read only. If you have a very large UnitOfWork
but know that a large set of entities has not changed, just mark them as read
only with ``$entityManager->getUnitOfWork()->markReadOnly($entity)``.
-- Flush only a single entity with ``$entityManager->flush($entity)``.
- Use :doc:`Change Tracking Policies ` to use more
explicit strategies of notifying the UnitOfWork what objects/properties
changed.
-.. note::
-
- Flush only a single entity with ``$entityManager->flush($entity)`` is deprecated and will be removed in ORM 3.0.
- (\ `Details `_)
-
Query Internals
---------------
diff --git a/docs/en/reference/working-with-associations.rst b/docs/en/reference/working-with-associations.rst
index 2c265679fa1..b5ca716ad07 100644
--- a/docs/en/reference/working-with-associations.rst
+++ b/docs/en/reference/working-with-associations.rst
@@ -415,7 +415,7 @@ Transitive persistence / Cascade Operations
Doctrine ORM provides a mechanism for transitive persistence through cascading of certain operations.
Each association to another entity or a collection of
entities can be configured to automatically cascade the following operations to the associated entities:
-``persist``, ``remove``, ``merge``, ``detach``, ``refresh`` or ``all``.
+``persist``, ``remove``, ``detach``, ``refresh`` or ``all``.
The main use case for ``cascade: persist`` is to avoid "exposing" associated entities to your PHP application.
Continuing with the User-Comment example of this chapter, this is how the creation of a new user and a new
diff --git a/docs/en/reference/working-with-objects.rst b/docs/en/reference/working-with-objects.rst
index cc889ddde3f..d780b553941 100644
--- a/docs/en/reference/working-with-objects.rst
+++ b/docs/en/reference/working-with-objects.rst
@@ -166,7 +166,7 @@ your code. See the following code:
Traversing the object graph for parts that are lazy-loaded will
easily trigger lots of SQL queries and will perform badly if used
- to heavily. Make sure to use DQL to fetch-join all the parts of the
+ too heavily. Make sure to use DQL to fetch-join all the parts of the
object-graph that you need as efficiently as possible.
@@ -414,77 +414,6 @@ automatically without invoking the ``detach`` method:
The ``detach`` operation is usually not as frequently needed and
used as ``persist`` and ``remove``.
-Merging entities
-----------------
-
-Merging entities refers to the merging of (usually detached)
-entities into the context of an EntityManager so that they become
-managed again. To merge the state of an entity into an
-EntityManager use the ``EntityManager#merge($entity)`` method. The
-state of the passed entity will be merged into a managed copy of
-this entity and this copy will subsequently be returned.
-
-Example:
-
-.. code-block:: php
-
- merge($detachedEntity);
- // $entity now refers to the fully managed copy returned by the merge operation.
- // The EntityManager $em now manages the persistence of $entity as usual.
-
-
-The semantics of the merge operation, applied to an entity X, are
-as follows:
-
-
-- If X is a detached entity, the state of X is copied onto a
- pre-existing managed entity instance X' of the same identity.
-- If X is a new entity instance, a new managed copy X' will be
- created and the state of X is copied onto this managed instance.
-- If X is a removed entity instance, an InvalidArgumentException
- will be thrown.
-- If X is a managed entity, it is ignored by the merge operation,
- however, the merge operation is cascaded to entities referenced by
- relationships from X if these relationships have been mapped with
- the cascade element value MERGE or ALL (see ":ref:`transitive-persistence`").
-- For all entities Y referenced by relationships from X having the
- cascade element value MERGE or ALL, Y is merged recursively as Y'.
- For all such Y referenced by X, X' is set to reference Y'. (Note
- that if X is managed then X is the same object as X'.)
-- If X is an entity merged to X', with a reference to another
- entity Y, where cascade=MERGE or cascade=ALL is not specified, then
- navigation of the same association from X' yields a reference to a
- managed object Y' with the same persistent identity as Y.
-
-The ``merge`` operation will throw an ``OptimisticLockException``
-if the entity being merged uses optimistic locking through a
-version field and the versions of the entity being merged and the
-managed copy don't match. This usually means that the entity has
-been modified while being detached.
-
-The ``merge`` operation is usually not as frequently needed and
-used as ``persist`` and ``remove``. The most common scenario for
-the ``merge`` operation is to reattach entities to an EntityManager
-that come from some cache (and are therefore detached) and you want
-to modify and persist such an entity.
-
-.. warning::
-
- If you need to perform multiple merges of entities that share certain subparts
- of their object-graphs and cascade merge, then you have to call ``EntityManager#clear()`` between the
- successive calls to ``EntityManager#merge()``. Otherwise you might end up with
- multiple copies of the "same" object in the database, however with different ids.
-
-.. note::
-
- If you load some detached entities from a cache and you do
- not need to persist or delete them or otherwise make use of them
- without the need for persistence services there is no need to use
- ``merge``. I.e. you can simply pass detached objects from a cache
- directly to the view.
-
Synchronization with the Database
---------------------------------
@@ -595,7 +524,7 @@ during development.
.. note::
Do not invoke ``flush`` after every change to an entity
- or every single invocation of persist/remove/merge/... This is an
+ or every single invocation of persist/remove/... This is an
anti-pattern and unnecessarily reduces the performance of your
application. Instead, form units of work that operate on your
objects and call ``flush`` when you are done. While serving a
@@ -863,7 +792,7 @@ By default the EntityManager returns a default implementation of
``Doctrine\ORM\EntityRepository`` when you call
``EntityManager#getRepository($entityClass)``. You can overwrite
this behaviour by specifying the class name of your own Entity
-Repository in the Attribute, Annotation, XML or YAML metadata. In large
+Repository in the Attribute or XML metadata. In large
applications that require lots of specialized DQL queries using a
custom repository is one recommended way of grouping these queries
in a central location.
diff --git a/docs/en/reference/xml-mapping.rst b/docs/en/reference/xml-mapping.rst
index c8c1abe51d4..e010c93690b 100644
--- a/docs/en/reference/xml-mapping.rst
+++ b/docs/en/reference/xml-mapping.rst
@@ -2,7 +2,8 @@ XML Mapping
===========
The XML mapping driver enables you to provide the ORM metadata in
-form of XML documents.
+form of XML documents. It requires the ``dom`` extension in order to be
+able to validate your mapping documents against its XML Schema.
The XML driver is backed by an XML Schema document that describes
the structure of a mapping document. The most recent version of the
@@ -691,7 +692,6 @@ specified by their respective tags:
- ````
-- ````
- ````
- ````
- ````
diff --git a/docs/en/reference/yaml-mapping.rst b/docs/en/reference/yaml-mapping.rst
deleted file mode 100644
index bb5feb9b870..00000000000
--- a/docs/en/reference/yaml-mapping.rst
+++ /dev/null
@@ -1,158 +0,0 @@
-YAML Mapping
-============
-
-.. warning::
- The YAML driver is deprecated and will be removed in version 3.0.
- It is strongly recommended to switch to one of the other mappings.
-
-The YAML mapping driver enables you to provide the ORM metadata in
-form of YAML documents.
-
-The YAML mapping document of a class is loaded on-demand the first
-time it is requested and subsequently stored in the metadata cache.
-In order to work, this requires certain conventions:
-
-
-- Each entity/mapped superclass must get its own dedicated YAML
- mapping document.
-- The name of the mapping document must consist of the fully
- qualified name of the class, where namespace separators are
- replaced by dots (.).
-- All mapping documents should get the extension ".dcm.yml" to
- identify it as a Doctrine mapping file. This is more of a
- convention and you are not forced to do this. You can change the
- file extension easily enough.
-
-.. code-block:: php
-
- setFileExtension('.yml');
-
-It is recommended to put all YAML mapping documents in a single
-folder but you can spread the documents over several folders if you
-want to. In order to tell the YamlDriver where to look for your
-mapping documents, supply an array of paths as the first argument
-of the constructor, like this:
-
-.. code-block:: php
-
- setMetadataDriverImpl($driver);
-
-Simplified YAML Driver
-~~~~~~~~~~~~~~~~~~~~~~
-
-The Symfony project sponsored a driver that simplifies usage of the YAML Driver.
-The changes between the original driver are:
-
-- File Extension is .orm.yml
-- Filenames are shortened, "MyProject\\Entities\\User" will become User.orm.yml
-- You can add a global file and add multiple entities in this file.
-
-Configuration of this client works a little bit different:
-
-.. code-block:: php
-
- 'MyProject\Entities',
- '/path/to/files2' => 'OtherProject\Entities'
- );
- $driver = new \Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver($namespaces);
- $driver->setGlobalBasename('global'); // global.orm.yml
-
-Example
--------
-
-As a quick start, here is a small example document that makes use
-of several common elements:
-
-.. code-block:: yaml
-
- # Doctrine.Tests.ORM.Mapping.User.dcm.yml
- Doctrine\Tests\ORM\Mapping\User:
- type: entity
- repositoryClass: Doctrine\Tests\ORM\Mapping\UserRepository
- table: cms_users
- schema: schema_name # The schema the table lies in, for platforms that support schemas (Optional, >= 2.5)
- readOnly: true
- indexes:
- name_index:
- columns: [ name ]
- id:
- id:
- type: integer
- generator:
- strategy: AUTO
- fields:
- name:
- type: string
- length: 50
- email:
- type: string
- length: 32
- column: user_email
- unique: true
- options:
- fixed: true
- comment: User's email address
- loginCount:
- type: integer
- column: login_count
- nullable: false
- options:
- unsigned: true
- default: 0
- oneToOne:
- address:
- targetEntity: Address
- joinColumn:
- name: address_id
- referencedColumnName: id
- onDelete: CASCADE
- oneToMany:
- phonenumbers:
- targetEntity: Phonenumber
- mappedBy: user
- cascade: ["persist", "merge"]
- manyToMany:
- groups:
- targetEntity: Group
- joinTable:
- name: cms_users_groups
- joinColumns:
- user_id:
- referencedColumnName: id
- inverseJoinColumns:
- group_id:
- referencedColumnName: id
- lifecycleCallbacks:
- prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ]
- postPersist: [ doStuffOnPostPersist ]
-
-Be aware that class-names specified in the YAML files should be
-fully qualified.
-
-Reference
-~~~~~~~~~~~~~~~~~~~~~~
-
-Unique Constraints
-------------------
-
-It is possible to define unique constraints by the following declaration:
-
-.. code-block:: yaml
-
- # ECommerceProduct.orm.yml
- ECommerceProduct:
- type: entity
- fields:
- # definition of some fields
- uniqueConstraints:
- search_idx:
- columns: [ name, email ]
-
diff --git a/docs/en/sidebar.rst b/docs/en/sidebar.rst
index b94c81fdd48..f52801c6b37 100644
--- a/docs/en/sidebar.rst
+++ b/docs/en/sidebar.rst
@@ -37,11 +37,10 @@
reference/query-builder
reference/native-sql
reference/change-tracking-policies
+ reference/partial-hydration
reference/partial-objects
- reference/annotations-reference
reference/attributes-reference
reference/xml-mapping
- reference/yaml-mapping
reference/php-mapping
reference/caching
reference/improving-performance
@@ -66,7 +65,6 @@
cookbook/dql-custom-walkers
cookbook/dql-user-defined-functions
cookbook/implementing-arrayaccess-for-domain-objects
- cookbook/implementing-the-notify-changetracking-policy
cookbook/resolve-target-entity-listener
cookbook/sql-table-prefixes
cookbook/strategy-cookbook-introduction
diff --git a/docs/en/tutorials/composite-primary-keys.rst b/docs/en/tutorials/composite-primary-keys.rst
index 386f8f140c0..f8cae53d91e 100644
--- a/docs/en/tutorials/composite-primary-keys.rst
+++ b/docs/en/tutorials/composite-primary-keys.rst
@@ -50,38 +50,6 @@ and year of production as primary keys:
}
}
- .. code-block:: annotation
-
- name = $name;
- $this->year = $year;
- }
-
- public function getModelName(): string
- {
- return $this->name;
- }
-
- public function getYearOfProduction(): int
- {
- return $this->year;
- }
- }
-
.. code-block:: xml
@@ -96,16 +64,6 @@ and year of production as primary keys:
- .. code-block:: yaml
-
- VehicleCatalogue\Model\Car:
- type: entity
- id:
- name:
- type: string
- year:
- type: integer
-
Now you can use this entity:
.. code-block:: php
@@ -127,11 +85,12 @@ And for querying you can use arrays to both DQL and EntityRepositories:
namespace VehicleCatalogue\Model;
// $em is the EntityManager
- $audi = $em->find("VehicleCatalogue\Model\Car", array("name" => "Audi A8", "year" => 2010));
+ $audi = $em->find("VehicleCatalogue\Model\Car", ["name" => "Audi A8", "year" => 2010]);
- $dql = "SELECT c FROM VehicleCatalogue\Model\Car c WHERE c.id = ?1";
+ $dql = "SELECT c FROM VehicleCatalogue\Model\Car c WHERE c.name = ?1 AND c.year = ?2";
$audi = $em->createQuery($dql)
- ->setParameter(1, ["name" => "Audi A8", "year" => 2010])
+ ->setParameter(1, "Audi A8")
+ ->setParameter(2, 2010)
->getSingleResult();
You can also use this entity in associations. Doctrine will then generate two foreign keys one for ``name``
@@ -160,7 +119,6 @@ The semantics of mapping identity through foreign entities are easy:
- Only allowed on Many-To-One or One-To-One associations.
- Plug an ``#[Id]`` attribute onto every association.
- Set an attribute ``association-key`` with the field name of the association in XML.
-- Set a key ``associationKey:`` with the field name of the association in YAML.
Use-Case 1: Dynamic Attributes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -214,57 +172,6 @@ We keep up the example of an Article with arbitrary attributes, the mapping look
}
}
- .. code-block:: annotation
-
-
- */
- private Collection $attributes;
-
- public function addAttribute($name, $value): void
- {
- $this->attributes[$name] = new ArticleAttribute($name, $value, $this);
- }
- }
-
- /**
- * @Entity
- */
- class ArticleAttribute
- {
- /** @Id @ManyToOne(targetEntity="Article", inversedBy="attributes") */
- private Article|null $article;
-
- /** @Id @Column(type="string") */
- private string $attribute;
-
- /** @Column(type="string") */
- private string $value;
-
- public function __construct($name, $value, $article)
- {
- $this->attribute = $name;
- $this->value = $value;
- $this->article = $article;
- }
- }
-
.. code-block:: xml
- .. code-block:: yaml
-
- Application\Model\ArticleAttribute:
- type: entity
- id:
- article:
- associationKey: true
- attribute:
- type: string
- fields:
- value:
- type: string
- manyToOne:
- article:
- targetEntity: Article
- inversedBy: attributes
-
-
Use-Case 2: Simple Derived Identity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -328,26 +217,6 @@ One good example for this is a user-address relationship:
private User|null $user = null;
}
- .. code-block:: yaml
-
- User:
- type: entity
- id:
- id:
- type: integer
- generator:
- strategy: AUTO
-
- Address:
- type: entity
- id:
- user:
- associationKey: true
- oneToOne:
- user:
- targetEntity: User
-
-
Use-Case 3: Join-Table with Metadata
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/en/tutorials/embeddables.rst b/docs/en/tutorials/embeddables.rst
index b298cb6a558..d0a8d517657 100644
--- a/docs/en/tutorials/embeddables.rst
+++ b/docs/en/tutorials/embeddables.rst
@@ -44,33 +44,6 @@ instead of simply adding the respective columns to the ``User`` class.
private string $country;
}
- .. code-block:: annotation
-
-
@@ -86,22 +59,6 @@ instead of simply adding the respective columns to the ``User`` class.
- .. code-block:: yaml
-
- User:
- type: entity
- embedded:
- address:
- class: Address
-
- Address:
- type: embeddable
- fields:
- street: { type: string }
- postalCode: { type: string }
- city: { type: string }
- country: { type: string }
-
In terms of your database schema, Doctrine will automatically inline all
columns from the ``Address`` class into the table of the ``User`` class,
just as if you had declared them directly there.
@@ -147,32 +104,12 @@ The following example shows you how to set your prefix to ``myPrefix_``:
private Address $address;
}
- .. code-block:: annotation
-
-
- .. code-block:: yaml
-
- User:
- type: entity
- embedded:
- address:
- class: Address
- columnPrefix: myPrefix_
-
To have Doctrine drop the prefix and use the value object's property name
directly, set ``columnPrefix=false`` (``use-column-prefix="false"`` for XML):
@@ -189,32 +126,12 @@ directly, set ``columnPrefix=false`` (``use-column-prefix="false"`` for XML):
private Address $address;
}
- .. code-block:: annotation
-
-
- .. code-block:: yaml
-
- User:
- type: entity
- embedded:
- address:
- class: Address
- columnPrefix: false
-
DQL
---
diff --git a/docs/en/tutorials/extra-lazy-associations.rst b/docs/en/tutorials/extra-lazy-associations.rst
index fbf1f00abd6..e2877a7649a 100644
--- a/docs/en/tutorials/extra-lazy-associations.rst
+++ b/docs/en/tutorials/extra-lazy-associations.rst
@@ -17,6 +17,7 @@ can be called without triggering a full load of the collection:
- ``Collection#contains($entity)``
- ``Collection#containsKey($key)``
- ``Collection#count()``
+- ``Collection#first()``
- ``Collection#get($key)``
- ``Collection#isEmpty()``
- ``Collection#slice($offset, $length = null)``
@@ -66,23 +67,6 @@ switch to extra lazy as shown in these examples:
public Collection $users;
}
- .. code-block:: annotation
-
-
- */
- public Collection $users;
- }
-
.. code-block:: xml
@@ -96,14 +80,3 @@ switch to extra lazy as shown in these examples:
-
- .. code-block:: yaml
-
- Doctrine\Tests\Models\CMS\CmsGroup:
- type: entity
- # ...
- manyToMany:
- users:
- targetEntity: CmsUser
- mappedBy: groups
- fetch: EXTRA_LAZY
diff --git a/docs/en/tutorials/getting-started.rst b/docs/en/tutorials/getting-started.rst
index 1fa463dd797..b972c119c51 100644
--- a/docs/en/tutorials/getting-started.rst
+++ b/docs/en/tutorials/getting-started.rst
@@ -27,7 +27,7 @@ What is Doctrine?
-----------------
Doctrine ORM is an `object-relational mapper (ORM) `_
-for PHP 7.1+ that provides transparent persistence for PHP objects. It uses the Data Mapper
+for PHP that provides transparent persistence for PHP objects. It uses the Data Mapper
pattern at the heart, aiming for a complete separation of your domain/business
logic from the persistence in a relational database management system.
@@ -82,10 +82,9 @@ that directory with the following contents:
{
"require": {
- "doctrine/orm": "^2.11.0",
- "doctrine/dbal": "^3.2",
- "symfony/yaml": "^5.4",
- "symfony/cache": "^5.4"
+ "doctrine/orm": "^3",
+ "doctrine/dbal": "^4",
+ "symfony/cache": "^7"
},
"autoload": {
"psr-0": {"": "src/"}
@@ -107,12 +106,8 @@ Add the following directories::
doctrine2-tutorial
|-- config
| `-- xml
- | `-- yaml
`-- src
-.. note::
- The YAML driver is deprecated and will be removed in version 3.0.
- It is strongly recommended to switch to one of the other mappings.
.. note::
It is strongly recommended that you require ``doctrine/dbal`` in your
``composer.json`` as well, because using the ORM means mapping objects
@@ -147,19 +142,11 @@ step:
paths: [__DIR__ . '/src'],
isDevMode: true,
);
- // or if you prefer annotation, YAML or XML
- // $config = ORMSetup::createAnnotationMetadataConfiguration(
- // paths: array(__DIR__."/src"),
- // isDevMode: true,
- // );
+ // or if you prefer XML
// $config = ORMSetup::createXMLMetadataConfiguration(
// paths: [__DIR__ . '/config/xml'],
// isDevMode: true,
//);
- // $config = ORMSetup::createYAMLMetadataConfiguration(
- // paths: array(__DIR__."/config/yaml"),
- // isDevMode: true,
- // );
// configuring the database connection
$connection = DriverManager::getConnection([
@@ -170,10 +157,6 @@ step:
// obtaining the entity manager
$entityManager = new EntityManager($connection, $config);
-.. note::
- The YAML driver is deprecated and will be removed in version 3.0.
- It is strongly recommended to switch to one of the other mappings.
-
The ``require_once`` statement sets up the class autoloading for Doctrine and
its dependencies using Composer's autoloader.
@@ -500,8 +483,8 @@ language describes how entities, their properties and references should be
persisted and what constraints should be applied to them.
Metadata for an Entity can be configured using attributes directly in
-the Entity class itself, or in an external XML or YAML file. This
-Getting Started guide will demonstrate metadata mappings using all three
+the Entity class itself, or in an external XML file. This
+Getting Started guide will demonstrate metadata mappings using both
methods, but you only need to choose one.
.. configuration-block::
@@ -527,33 +510,6 @@ methods, but you only need to choose one.
// .. (other code)
}
- .. code-block:: annotation
-
-
@@ -571,25 +527,6 @@ methods, but you only need to choose one.
-.. note::
- The YAML driver is deprecated and will be removed in version 3.0.
- It is strongly recommended to switch to one of the other mappings.
-
- .. code-block:: yaml
-
- # config/yaml/Product.dcm.yml
- Product:
- type: entity
- table: products
- id:
- id:
- type: integer
- generator:
- strategy: AUTO
- fields:
- name:
- type: string
-
The top-level ``entity`` definition specifies information about
the class and table name. The primitive type ``Product#name`` is
defined as a ``field`` attribute. The ``id`` property is defined with
@@ -1082,59 +1019,6 @@ the ``Product`` before:
// ... (other code)
}
- .. code-block:: annotation
-
-
@@ -1159,40 +1043,6 @@ the ``Product`` before:
-.. note::
- The YAML driver is deprecated and will be removed in version 3.0.
- It is strongly recommended to switch to one of the other mappings.
-
- .. code-block:: yaml
-
- # config/yaml/Bug.dcm.yml
- Bug:
- type: entity
- table: bugs
- id:
- id:
- type: integer
- generator:
- strategy: AUTO
- fields:
- description:
- type: text
- created:
- type: datetime
- status:
- type: string
- manyToOne:
- reporter:
- targetEntity: User
- inversedBy: reportedBugs
- engineer:
- targetEntity: User
- inversedBy: assignedBugs
- manyToMany:
- products:
- targetEntity: Product
-
-
Here we have the entity, id and primitive type definitions.
For the "created" field we have used the ``datetime`` type,
which translates the YYYY-mm-dd HH:mm:ss database format
@@ -1249,47 +1099,6 @@ Finally, we'll add metadata mappings for the ``User`` entity.
// .. (other code)
}
- .. code-block:: annotation
-
- An ArrayCollection of Bug objects.
- */
- private Collection $reportedBugs;
-
- /**
- * @ORM\OneToMany(targetEntity="Bug", mappedBy="engineer")
- * @var Collection An ArrayCollection of Bug objects.
- */
- private Collection $assignedBugs;
-
- // .. (other code)
- }
.. code-block:: xml
@@ -1310,33 +1119,7 @@ Finally, we'll add metadata mappings for the ``User`` entity.
-.. note::
- The YAML driver is deprecated and will be removed in version 3.0.
- It is strongly recommended to switch to one of the other mappings.
-
- .. code-block:: yaml
-
- # config/yaml/User.dcm.yml
- User:
- type: entity
- table: users
- id:
- id:
- type: integer
- generator:
- strategy: AUTO
- fields:
- name:
- type: string
- oneToMany:
- reportedBugs:
- targetEntity: Bug
- mappedBy: reporter
- assignedBugs:
- targetEntity: Bug
- mappedBy: engineer
-
-Here are some new things to mention about the ``OneToMany`` attribute.
+Here are some new things to mention about the ``one-to-many`` tags.
Remember that we discussed about the inverse and owning side. Now
both reportedBugs and assignedBugs are inverse relations, which
means the join details have already been defined on the owning
@@ -1800,21 +1583,6 @@ we have to adjust the metadata slightly.
// ...
}
- .. code-block:: annotation
-
-
-.. note::
- The YAML driver is deprecated and will be removed in version 3.0.
- It is strongly recommended to switch to one of the other mappings.
-
- .. code-block:: yaml
-
- Bug:
- type: entity
- repositoryClass: BugRepository
-
Now we can remove our query logic in all the places and instead use them through the EntityRepository.
As an example here is the code of the first use case "List of Bugs":
diff --git a/docs/en/tutorials/ordered-associations.rst b/docs/en/tutorials/ordered-associations.rst
index 9e414e0680e..e03eb45bf7a 100644
--- a/docs/en/tutorials/ordered-associations.rst
+++ b/docs/en/tutorials/ordered-associations.rst
@@ -27,22 +27,6 @@ can specify the ``#[OrderBy]`` in the following way:
private Collection $groups;
}
- .. code-block:: annotation
-
-
- */
- private Collection $groups;
- }
-
.. code-block:: xml
@@ -55,23 +39,6 @@ can specify the ``#[OrderBy]`` in the following way:
- .. code-block:: yaml
-
- User:
- type: entity
- manyToMany:
- groups:
- orderBy: { 'name': 'ASC' }
- targetEntity: Group
- joinTable:
- name: users_groups
- joinColumns:
- user_id:
- referencedColumnName: id
- inverseJoinColumns:
- group_id:
- referencedColumnName: id
-
The DQL Snippet in OrderBy is only allowed to consist of
unqualified, unquoted field names and of an optional ASC/DESC
positional statement. Multiple Fields are separated by a comma (,).
diff --git a/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst b/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst
index b7f74adf387..f81faba7122 100644
--- a/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst
+++ b/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst
@@ -64,7 +64,7 @@ which has mapping metadata that is overridden by the attribute above:
#[Column(name: 'trait_foo', type: 'integer', length: 100, nullable: true, unique: true)]
protected int $foo;
- #[OneToOne(targetEntity: Bar::class, cascade: ['persist', 'merge'])]
+ #[OneToOne(targetEntity: Bar::class, cascade: ['persist'])]
#[JoinColumn(name: 'example_trait_bar_id', referencedColumnName: 'id')]
protected Bar|null $bar = null;
}
@@ -79,4 +79,4 @@ The case for just extending a class would be just the same but:
// ...
}
-Overriding is also supported via XML and YAML (:ref:`examples `).
+Overriding is also supported via XML (:ref:`examples `).
diff --git a/docs/en/tutorials/working-with-indexed-associations.rst b/docs/en/tutorials/working-with-indexed-associations.rst
index e6822de3952..e15cae87aa4 100644
--- a/docs/en/tutorials/working-with-indexed-associations.rst
+++ b/docs/en/tutorials/working-with-indexed-associations.rst
@@ -24,9 +24,7 @@ Mapping Indexed Associations
You can map indexed associations by adding:
* ``indexBy`` argument to any ``#[OneToMany]`` or ``#[ManyToMany]`` attribute.
- * ``indexBy`` attribute to any ``@OneToMany`` or ``@ManyToMany`` annotation.
* ``index-by`` attribute to any ```` or ```` xml element.
- * ``indexBy:`` key-value pair to any association defined in ``manyToMany:`` or ``oneToMany:`` YAML mapping files.
The code and mappings for the Market entity looks like this:
@@ -34,16 +32,9 @@ The code and mappings for the Market entity looks like this:
.. literalinclude:: working-with-indexed-associations/Market.php
:language: attribute
- .. literalinclude:: working-with-indexed-associations/Market-annotations.php
- :language: annotation
-
.. literalinclude:: working-with-indexed-associations/market.xml
:language: xml
- .. literalinclude:: working-with-indexed-associations/market.yaml
- :language: yaml
-
-
Inside the ``addStock()`` method you can see how we directly set the key of the association to the symbol,
so that we can work with the indexed association directly after invoking ``addStock()``. Inside ``getStock($symbol)``
we pick a stock traded on the particular market by symbol. If this stock doesn't exist an exception is thrown.
@@ -83,47 +74,6 @@ here are the code and mappings for it:
}
}
- .. code-block:: annotation
-
- symbol = $symbol;
- $this->market = $market;
- $market->addStock($this);
- }
-
- public function getSymbol(): string
- {
- return $this->symbol;
- }
- }
-
.. code-block:: xml
@@ -142,23 +92,6 @@ here are the code and mappings for it:
- .. code-block:: yaml
-
- Doctrine\Tests\Models\StockExchange\Stock:
- type: entity
- id:
- id:
- type: integer
- generator:
- strategy: AUTO
- fields:
- symbol:
- type: string
- manyToOne:
- market:
- targetEntity: Market
- inversedBy: stocks
-
Querying indexed associations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/en/tutorials/working-with-indexed-associations/Market-annotations.php b/docs/en/tutorials/working-with-indexed-associations/Market-annotations.php
deleted file mode 100644
index 798b49d1d02..00000000000
--- a/docs/en/tutorials/working-with-indexed-associations/Market-annotations.php
+++ /dev/null
@@ -1,74 +0,0 @@
-
- */
- private Collection $stocks;
-
- public function __construct($name)
- {
- $this->name = $name;
- $this->stocks = new ArrayCollection();
- }
-
- public function getId(): int|null
- {
- return $this->id;
- }
-
- public function getName(): string
- {
- return $this->name;
- }
-
- public function addStock(Stock $stock): void
- {
- $this->stocks[$stock->getSymbol()] = $stock;
- }
-
- public function getStock($symbol): Stock
- {
- if (!isset($this->stocks[$symbol])) {
- throw new InvalidArgumentException("Symbol is not traded on this market.");
- }
-
- return $this->stocks[$symbol];
- }
-
- /** @return array */
- public function getStocks(): array
- {
- return $this->stocks->toArray();
- }
-}
diff --git a/docs/en/tutorials/working-with-indexed-associations/market.yaml b/docs/en/tutorials/working-with-indexed-associations/market.yaml
deleted file mode 100644
index b7c8132e090..00000000000
--- a/docs/en/tutorials/working-with-indexed-associations/market.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-Doctrine\Tests\Models\StockExchange\Market:
- type: entity
- id:
- id:
- type: integer
- generator:
- strategy: AUTO
- fields:
- name:
- type:string
- oneToMany:
- stocks:
- targetEntity: Stock
- mappedBy: market
- indexBy: symbol
diff --git a/doctrine-mapping.xsd b/doctrine-mapping.xsd
index 651c9d29c09..6131026f5f6 100644
--- a/doctrine-mapping.xsd
+++ b/doctrine-mapping.xsd
@@ -35,7 +35,6 @@
-
@@ -82,36 +81,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -143,23 +112,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -175,9 +127,6 @@
-
-
-
@@ -239,7 +188,6 @@
-
@@ -247,7 +195,6 @@
-
@@ -257,7 +204,6 @@
-
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index ec9ff9f2cc3..34ecdf46afc 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -11,7 +11,7 @@
-
+ srctests
@@ -20,38 +20,38 @@
*/tests/Tests/ORM/Tools/Export/export/*
-
-
-
-
-
-
-
- */tests/*
+
- */src/*tests/Tests/Mocks/HydratorMockStatement.php
+ tests/Tests/Models/Cache/ComplexAction.php
+ tests/Tests/Models/DDC117/DDC117ArticleDetails.php
+ tests/Tests/Models/DDC117/DDC117Translation.php
+ tests/Tests/ORM/Functional/Ticket/DDC2579Test.php
+ tests/Tests/ORM/Functional/ValueObjectsTest.php
-
- */src/*
+
+ tests/*
+
+
+
+ tests/*
- src/Mapping/Driver/CompatibilityAnnotationDriver.php
- src/Tools/Console/CommandCompatibility.php
- src/Tools/Console/Helper/EntityManagerHelper.php
+ src/Mapping/Driver/LoadMappingFileImplementation.php
+ src/Mapping/GetReflectionClassImplementation.phptests/*
@@ -70,14 +70,6 @@
src/Tools/ToolEvents.php
-
-
- src/Mapping/Column.php
- src/Mapping/Index.php
- src/Mapping/Table.php
- src/Mapping/UniqueConstraint.php
-
-
src/Internal/Hydration/AbstractHydrator.php
@@ -94,7 +86,6 @@
src/Mapping/Cache.phpsrc/Mapping/ChangeTrackingPolicy.phpsrc/Mapping/Column.php
- src/Mapping/ColumnResult.phpsrc/Mapping/CustomIdGenerator.phpsrc/Mapping/DiscriminatorColumn.phpsrc/Mapping/DiscriminatorMap.php
@@ -102,8 +93,6 @@
src/Mapping/Embedded.phpsrc/Mapping/Entity.phpsrc/Mapping/EntityListeners.php
- src/Mapping/EntityResult.php
- src/Mapping/FieldResult.phpsrc/Mapping/GeneratedValue.phpsrc/Mapping/HasLifecycleCallbacks.phpsrc/Mapping/Id.php
@@ -115,10 +104,6 @@
src/Mapping/ManyToMany.phpsrc/Mapping/ManyToOne.phpsrc/Mapping/MappedSuperclass.php
- src/Mapping/NamedNativeQueries.php
- src/Mapping/NamedNativeQuery.php
- src/Mapping/NamedQueries.php
- src/Mapping/NamedQuery.phpsrc/Mapping/OneToMany.phpsrc/Mapping/OneToOne.phpsrc/Mapping/OrderBy.php
@@ -131,8 +116,6 @@
src/Mapping/PreRemove.phpsrc/Mapping/PreUpdate.phpsrc/Mapping/SequenceGenerator.php
- src/Mapping/SqlResultSetMapping.php
- src/Mapping/SqlResultSetMappings.phpsrc/Mapping/Table.phpsrc/Mapping/UniqueConstraint.phpsrc/Mapping/Version.php
@@ -142,6 +125,36 @@
src/Cache/DefaultQueryCache.php
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
src/EntityManagerInterface.php
@@ -197,9 +210,6 @@
tests/Tests/Models/DDC1590/DDC1590User.php
-
- tests/Tests/ORM/Functional/Ticket/DDC832Test.php
-
@@ -224,34 +234,20 @@
src/AbstractQuery.php
- src/Mapping/ClassMetadataInfo.php
+ src/Mapping/ClassMetadata.phpsrc/NativeQuery.phpsrc/Query.phpsrc/Query/TreeWalkerAdapter.phpsrc/Tools/Export/Driver/AbstractExporter.php
- src/Tools/Export/Driver/AnnotationExporter.phpsrc/Tools/Export/Driver/PhpExporter.phptests/Tests/Mocks/DatabasePlatformMock.phptests/Tests/Mocks/SchemaManagerMock.php
+ tests/Tests/ORM/AbstractQueryTest.phptests/Tests/ORM/Functional/Ticket/DDC3634Test.php
- src/AbstractQuery.php
- src/Configuration.php
- src/EntityRepository.php
- src/Internal/Hydration/AbstractHydrator.php
- src/Query/Exec/AbstractSqlExecutor.php
- src/Query/Exec/AbstractSqlExecutor.php
- src/Query/Printer.php
- src/Tools/EntityRepositoryGenerator.php
- src/Tools/Console/Helper/EntityManagerHelper.php
- src/Tools/Export/Driver/AbstractExporter.php
- src/Tools/Export/Driver/AnnotationExporter.php
- src/Tools/Export/Driver/PhpExporter.php
- src/Tools/Export/Driver/XmlExporter.php
- src/Tools/Export/Driver/YamlExporter.phptests/Tests/OrmFunctionalTestCase.php
@@ -266,6 +262,7 @@
tests/Tests/ORM/Functional/Ticket/DDC1885Test.phptests/Tests/ORM/Functional/Ticket/DDC1843Test.php
+ tests/Tests/ORM/Mapping/ClassMetadataFactoryTest.php
@@ -280,9 +277,4 @@
src/QueryBuilder.php
-
-
-
- src/Mapping/Driver/XmlDriver.php
-
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index 252cad57c2a..44cb4153e21 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -1,23 +1,5 @@
parameters:
ignoreErrors:
- -
- message: '#^Call to function method_exists\(\) with ''Doctrine\\\\DBAL\\\\Cache\\\\QueryCacheProfile'' and ''setResultCache'' will always evaluate to true\.$#'
- identifier: function.alreadyNarrowedType
- count: 3
- path: src/AbstractQuery.php
-
- -
- message: '#^Call to function method_exists\(\) with Doctrine\\DBAL\\Cache\\QueryCacheProfile and ''getResultCache'' will always evaluate to true\.$#'
- identifier: function.alreadyNarrowedType
- count: 1
- path: src/AbstractQuery.php
-
- -
- message: '#^Call to function method_exists\(\) with Doctrine\\DBAL\\Cache\\QueryCacheProfile and ''setResultCache'' will always evaluate to true\.$#'
- identifier: function.alreadyNarrowedType
- count: 1
- path: src/AbstractQuery.php
-
-
message: '#^Expression "\$setCacheEntry\(\$data\)" on a separate line does not do anything\.$#'
identifier: expr.resultUnused
@@ -37,35 +19,11 @@ parameters:
path: src/AbstractQuery.php
-
- message: '#^Parameter \#1 \$parameters of method Doctrine\\ORM\\AbstractQuery\:\:setParameters\(\) expects array\\|Doctrine\\Common\\Collections\\ArrayCollection\, iterable\<\(int\|string\), mixed\> given\.$#'
- identifier: argument.type
- count: 1
- path: src/AbstractQuery.php
-
- -
- message: '#^Parameter \#1 \$stmt of method Doctrine\\ORM\\Internal\\Hydration\\AbstractHydrator\:\:iterate\(\) expects Doctrine\\DBAL\\Driver\\ResultStatement\|Doctrine\\DBAL\\Result, Doctrine\\DBAL\\Result\|int given\.$#'
- identifier: argument.type
- count: 1
- path: src/AbstractQuery.php
-
- -
- message: '#^Parameter \#1 \$stmt of method Doctrine\\ORM\\Internal\\Hydration\\AbstractHydrator\:\:toIterable\(\) expects Doctrine\\DBAL\\Driver\\ResultStatement\|Doctrine\\DBAL\\Result, Doctrine\\DBAL\\Result\|int given\.$#'
- identifier: argument.type
- count: 1
- path: src/AbstractQuery.php
-
- -
- message: '#^Parameter \#1 \$value of function count expects array\|Countable, iterable\<\(int\|string\), mixed\> given\.$#'
+ message: '#^Parameter \#1 \$stmt of method Doctrine\\ORM\\Internal\\Hydration\\AbstractHydrator\:\:toIterable\(\) expects Doctrine\\DBAL\\Result, Doctrine\\DBAL\\Result\|int given\.$#'
identifier: argument.type
count: 1
path: src/AbstractQuery.php
- -
- message: '#^Method Doctrine\\ORM\\Cache\\CacheFactory\:\:buildCachedCollectionPersister\(\) has parameter \$mapping with no value type specified in iterable type array\.$#'
- identifier: missingType.iterableValue
- count: 5
- path: src/Cache/CacheFactory.php
-
-
message: '#^Method Doctrine\\ORM\\Cache\\CacheFactory\:\:buildCachedEntityPersister\(\) has parameter \$metadata with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
identifier: missingType.generics
@@ -84,6 +42,18 @@ parameters:
count: 1
path: src/Cache/CollectionHydrator.php
+ -
+ message: '#^Method Doctrine\\ORM\\Cache\\CollectionHydrator\:\:buildCacheEntry\(\) has parameter \$collection with no value type specified in iterable type array\.$#'
+ identifier: missingType.iterableValue
+ count: 1
+ path: src/Cache/CollectionHydrator.php
+
+ -
+ message: '#^Method Doctrine\\ORM\\Cache\\CollectionHydrator\:\:buildCacheEntry\(\) has parameter \$collection with no value type specified in iterable type array\|\(Doctrine\\Common\\Collections\\Collection&iterable\)\.$#'
+ identifier: missingType.iterableValue
+ count: 1
+ path: src/Cache/CollectionHydrator.php
+
-
message: '#^Method Doctrine\\ORM\\Cache\\CollectionHydrator\:\:buildCacheEntry\(\) has parameter \$metadata with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
identifier: missingType.generics
@@ -120,18 +90,6 @@ parameters:
count: 1
path: src/Cache/DefaultCache.php
- -
- message: '#^Instanceof between Psr\\Cache\\CacheItemPoolInterface and Psr\\Cache\\CacheItemPoolInterface will always evaluate to true\.$#'
- identifier: instanceof.alwaysTrue
- count: 1
- path: src/Cache/DefaultCacheFactory.php
-
- -
- message: '#^Method Doctrine\\ORM\\Cache\\DefaultCacheFactory\:\:buildCachedCollectionPersister\(\) has parameter \$mapping with no value type specified in iterable type array\.$#'
- identifier: missingType.iterableValue
- count: 5
- path: src/Cache/DefaultCacheFactory.php
-
-
message: '#^Method Doctrine\\ORM\\Cache\\DefaultCacheFactory\:\:buildCachedEntityPersister\(\) has parameter \$metadata with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
identifier: missingType.generics
@@ -150,6 +108,18 @@ parameters:
count: 1
path: src/Cache/DefaultCollectionHydrator.php
+ -
+ message: '#^Method Doctrine\\ORM\\Cache\\DefaultCollectionHydrator\:\:buildCacheEntry\(\) has parameter \$collection with no value type specified in iterable type array\.$#'
+ identifier: missingType.iterableValue
+ count: 1
+ path: src/Cache/DefaultCollectionHydrator.php
+
+ -
+ message: '#^Method Doctrine\\ORM\\Cache\\DefaultCollectionHydrator\:\:buildCacheEntry\(\) has parameter \$collection with no value type specified in iterable type array\|\(Doctrine\\Common\\Collections\\Collection&iterable\)\.$#'
+ identifier: missingType.iterableValue
+ count: 1
+ path: src/Cache/DefaultCollectionHydrator.php
+
-
message: '#^Method Doctrine\\ORM\\Cache\\DefaultCollectionHydrator\:\:buildCacheEntry\(\) has parameter \$metadata with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
identifier: missingType.generics
@@ -169,33 +139,39 @@ parameters:
path: src/Cache/DefaultCollectionHydrator.php
-
- message: '#^Call to an undefined method Doctrine\\ORM\\Persisters\\Entity\\EntityPersister\:\:getCacheRegion\(\)\.$#'
- identifier: method.notFound
+ message: '#^Access to an undefined property Doctrine\\ORM\\Mapping\\ManyToManyInverseSideMapping\|Doctrine\\ORM\\Mapping\\ManyToManyOwningSideMapping\|Doctrine\\ORM\\Mapping\\ManyToOneAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToManyAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToOneInverseSideMapping\|Doctrine\\ORM\\Mapping\\OneToOneOwningSideMapping\:\:\$joinColumnFieldNames\.$#'
+ identifier: property.notFound
count: 1
path: src/Cache/DefaultEntityHydrator.php
-
- message: '#^Method Doctrine\\ORM\\Cache\\DefaultEntityHydrator\:\:buildCacheEntry\(\) has parameter \$metadata with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
- identifier: missingType.generics
+ message: '#^Access to an undefined property Doctrine\\ORM\\Mapping\\ManyToManyInverseSideMapping\|Doctrine\\ORM\\Mapping\\ManyToManyOwningSideMapping\|Doctrine\\ORM\\Mapping\\ManyToOneAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToManyAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToOneInverseSideMapping\|Doctrine\\ORM\\Mapping\\OneToOneOwningSideMapping\:\:\$targetToSourceKeyColumns\.$#'
+ identifier: property.notFound
count: 1
path: src/Cache/DefaultEntityHydrator.php
-
- message: '#^Method Doctrine\\ORM\\Cache\\DefaultEntityHydrator\:\:loadCacheEntry\(\) has parameter \$metadata with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
- identifier: missingType.generics
+ message: '#^Access to an undefined property Doctrine\\ORM\\Mapping\\ManyToManyOwningSideMapping\|Doctrine\\ORM\\Mapping\\ManyToOneAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToOneOwningSideMapping\:\:\$targetToSourceKeyColumns\.$#'
+ identifier: property.notFound
count: 1
path: src/Cache/DefaultEntityHydrator.php
-
- message: '#^Offset ''joinColumnFieldNames'' might not exist on array\{cache\: array, cascade\: array\, declared\?\: class\-string, fetch\: mixed, fieldName\: string, id\: bool, inherited\?\: class\-string, indexBy\?\: string, \.\.\.\}\.$#'
- identifier: offsetAccess.notFound
+ message: '#^Call to an undefined method Doctrine\\ORM\\Persisters\\Entity\\EntityPersister\:\:getCacheRegion\(\)\.$#'
+ identifier: method.notFound
count: 1
path: src/Cache/DefaultEntityHydrator.php
-
- message: '#^Offset ''targetToSourceKeyColumns'' might not exist on array\{cache\?\: array, cascade\: array\, declared\?\: class\-string, fetch\: mixed, fieldName\: string, id\?\: bool, inherited\?\: class\-string, indexBy\?\: string, \.\.\.\}\.$#'
- identifier: offsetAccess.notFound
- count: 2
+ message: '#^Method Doctrine\\ORM\\Cache\\DefaultEntityHydrator\:\:buildCacheEntry\(\) has parameter \$metadata with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
+ identifier: missingType.generics
+ count: 1
+ path: src/Cache/DefaultEntityHydrator.php
+
+ -
+ message: '#^Method Doctrine\\ORM\\Cache\\DefaultEntityHydrator\:\:loadCacheEntry\(\) has parameter \$metadata with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
+ identifier: missingType.generics
+ count: 1
path: src/Cache/DefaultEntityHydrator.php
-
@@ -234,12 +210,6 @@ parameters:
count: 2
path: src/Cache/DefaultQueryCache.php
- -
- message: '#^Method Doctrine\\ORM\\Cache\\DefaultQueryCache\:\:storeAssociationCache\(\) has parameter \$assoc with no value type specified in iterable type array\.$#'
- identifier: missingType.iterableValue
- count: 5
- path: src/Cache/DefaultQueryCache.php
-
-
message: '#^Method Doctrine\\ORM\\Cache\\DefaultQueryCache\:\:storeAssociationCache\(\) return type has no value type specified in iterable type array\.$#'
identifier: missingType.iterableValue
@@ -300,18 +270,6 @@ parameters:
count: 1
path: src/Cache/Persister/Collection/AbstractCollectionPersister.php
- -
- message: '#^Instanceof between Doctrine\\Common\\Collections\\Collection&iterable and Doctrine\\Common\\Collections\\Collection will always evaluate to true\.$#'
- identifier: instanceof.alwaysTrue
- count: 1
- path: src/Cache/Persister/Collection/AbstractCollectionPersister.php
-
- -
- message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Collection\\AbstractCollectionPersister\:\:__construct\(\) has parameter \$association with no value type specified in iterable type array\.$#'
- identifier: missingType.iterableValue
- count: 5
- path: src/Cache/Persister/Collection/AbstractCollectionPersister.php
-
-
message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Collection\\AbstractCollectionPersister\:\:contains\(\) has parameter \$collection with generic class Doctrine\\ORM\\PersistentCollection but does not specify its types\: TKey, T$#'
identifier: missingType.generics
@@ -330,12 +288,6 @@ parameters:
count: 1
path: src/Cache/Persister/Collection/AbstractCollectionPersister.php
- -
- message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Collection\\AbstractCollectionPersister\:\:evictCollectionCache\(\) has parameter \$collection with generic class Doctrine\\ORM\\PersistentCollection but does not specify its types\: TKey, T$#'
- identifier: missingType.generics
- count: 1
- path: src/Cache/Persister/Collection/AbstractCollectionPersister.php
-
-
message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Collection\\AbstractCollectionPersister\:\:get\(\) has parameter \$collection with generic class Doctrine\\ORM\\PersistentCollection but does not specify its types\: TKey, T$#'
identifier: missingType.generics
@@ -379,8 +331,14 @@ parameters:
path: src/Cache/Persister/Collection/AbstractCollectionPersister.php
-
- message: '#^Parameter \#1 \$array \(list\\) of array_values is already a list, call has no effect\.$#'
- identifier: arrayValues.list
+ message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Collection\\AbstractCollectionPersister\:\:storeCollectionCache\(\) has parameter \$elements with no value type specified in iterable type array\.$#'
+ identifier: missingType.iterableValue
+ count: 1
+ path: src/Cache/Persister/Collection/AbstractCollectionPersister.php
+
+ -
+ message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Collection\\AbstractCollectionPersister\:\:storeCollectionCache\(\) has parameter \$elements with no value type specified in iterable type array\|\(Doctrine\\Common\\Collections\\Collection&iterable\)\.$#'
+ identifier: missingType.iterableValue
count: 1
path: src/Cache/Persister/Collection/AbstractCollectionPersister.php
@@ -432,6 +390,18 @@ parameters:
count: 1
path: src/Cache/Persister/Collection/CachedCollectionPersister.php
+ -
+ message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Collection\\CachedCollectionPersister\:\:storeCollectionCache\(\) has parameter \$elements with no value type specified in iterable type array\.$#'
+ identifier: missingType.iterableValue
+ count: 1
+ path: src/Cache/Persister/Collection/CachedCollectionPersister.php
+
+ -
+ message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Collection\\CachedCollectionPersister\:\:storeCollectionCache\(\) has parameter \$elements with no value type specified in iterable type array\|\(Doctrine\\Common\\Collections\\Collection&iterable\)\.$#'
+ identifier: missingType.iterableValue
+ count: 1
+ path: src/Cache/Persister/Collection/CachedCollectionPersister.php
+
-
message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Collection\\NonStrictReadWriteCachedCollectionPersister\:\:delete\(\) has parameter \$collection with generic class Doctrine\\ORM\\PersistentCollection but does not specify its types\: TKey, T$#'
identifier: missingType.generics
@@ -456,12 +426,6 @@ parameters:
count: 2
path: src/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php
- -
- message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Collection\\ReadWriteCachedCollectionPersister\:\:__construct\(\) has parameter \$association with no value type specified in iterable type array\.$#'
- identifier: missingType.iterableValue
- count: 5
- path: src/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php
-
-
message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Collection\\ReadWriteCachedCollectionPersister\:\:delete\(\) has parameter \$collection with generic class Doctrine\\ORM\\PersistentCollection but does not specify its types\: TKey, T$#'
identifier: missingType.generics
@@ -498,12 +462,6 @@ parameters:
count: 1
path: src/Cache/Persister/Entity/AbstractEntityPersister.php
- -
- message: '#^Call to function method_exists\(\) with ''Doctrine\\\\Common\\\\Collections\\\\Criteria'' and ''orderings'' will always evaluate to true\.$#'
- identifier: function.alreadyNarrowedType
- count: 1
- path: src/Cache/Persister/Entity/AbstractEntityPersister.php
-
-
message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Entity\\AbstractEntityPersister\:\:__construct\(\) has parameter \$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
identifier: missingType.generics
@@ -516,84 +474,24 @@ parameters:
count: 1
path: src/Cache/Persister/Entity/AbstractEntityPersister.php
- -
- message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Entity\\AbstractEntityPersister\:\:getManyToManyCollection\(\) has parameter \$assoc with no value type specified in iterable type array\.$#'
- identifier: missingType.iterableValue
- count: 5
- path: src/Cache/Persister/Entity/AbstractEntityPersister.php
-
- -
- message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Entity\\AbstractEntityPersister\:\:getOneToManyCollection\(\) has parameter \$assoc with no value type specified in iterable type array\.$#'
- identifier: missingType.iterableValue
- count: 5
- path: src/Cache/Persister/Entity/AbstractEntityPersister.php
-
- -
- message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Entity\\AbstractEntityPersister\:\:getSelectConditionStatementSQL\(\) has parameter \$assoc with no value type specified in iterable type array\.$#'
- identifier: missingType.iterableValue
- count: 5
- path: src/Cache/Persister/Entity/AbstractEntityPersister.php
-
- -
- message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Entity\\AbstractEntityPersister\:\:getSelectSQL\(\) has parameter \$assoc with no value type specified in iterable type array\.$#'
- identifier: missingType.iterableValue
- count: 5
- path: src/Cache/Persister/Entity/AbstractEntityPersister.php
-
- -
- message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Entity\\AbstractEntityPersister\:\:load\(\) has parameter \$assoc with no value type specified in iterable type array\.$#'
- identifier: missingType.iterableValue
- count: 5
- path: src/Cache/Persister/Entity/AbstractEntityPersister.php
-
- -
- message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Entity\\AbstractEntityPersister\:\:loadAll\(\) has no return type specified\.$#'
- identifier: missingType.return
- count: 1
- path: src/Cache/Persister/Entity/AbstractEntityPersister.php
-
- -
- message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Entity\\AbstractEntityPersister\:\:loadManyToManyCollection\(\) has parameter \$assoc with no value type specified in iterable type array\.$#'
- identifier: missingType.iterableValue
- count: 5
- path: src/Cache/Persister/Entity/AbstractEntityPersister.php
-
-
message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Entity\\AbstractEntityPersister\:\:loadManyToManyCollection\(\) has parameter \$collection with generic class Doctrine\\ORM\\PersistentCollection but does not specify its types\: TKey, T$#'
identifier: missingType.generics
count: 1
path: src/Cache/Persister/Entity/AbstractEntityPersister.php
- -
- message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Entity\\AbstractEntityPersister\:\:loadOneToManyCollection\(\) has parameter \$assoc with no value type specified in iterable type array\.$#'
- identifier: missingType.iterableValue
- count: 5
- path: src/Cache/Persister/Entity/AbstractEntityPersister.php
-
-
message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Entity\\AbstractEntityPersister\:\:loadOneToManyCollection\(\) has parameter \$collection with generic class Doctrine\\ORM\\PersistentCollection but does not specify its types\: TKey, T$#'
identifier: missingType.generics
count: 1
path: src/Cache/Persister/Entity/AbstractEntityPersister.php
- -
- message: '#^Method Doctrine\\ORM\\Cache\\Persister\\Entity\\AbstractEntityPersister\:\:loadOneToOneEntity\(\) has parameter \$assoc with no value type specified in iterable type array\.$#'
- identifier: missingType.iterableValue
- count: 5
- path: src/Cache/Persister/Entity/AbstractEntityPersister.php
-
-
message: '#^Parameter \#3 \$entry of method Doctrine\\ORM\\Cache\\EntityHydrator\:\:loadCacheEntry\(\) expects Doctrine\\ORM\\Cache\\EntityCacheEntry, Doctrine\\ORM\\Cache\\CacheEntry given\.$#'
identifier: argument.type
count: 1
path: src/Cache/Persister/Entity/AbstractEntityPersister.php
- -
- message: '#^Property Doctrine\\ORM\\Cache\\Persister\\Entity\\AbstractEntityPersister\:\:\$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata does not specify its types\: T$#'
- identifier: missingType.generics
- count: 1
- path: src/Cache/Persister/Entity/AbstractEntityPersister.php
-
-
message: '#^Call to an undefined method Doctrine\\ORM\\Cache\\Region\:\:lock\(\)\.$#'
identifier: method.notFound
@@ -612,42 +510,12 @@ parameters:
count: 1
path: src/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php
- -
- message: '#^Instanceof between Psr\\Cache\\CacheItemPoolInterface and Psr\\Cache\\CacheItemPoolInterface will always evaluate to true\.$#'
- identifier: instanceof.alwaysTrue
- count: 1
- path: src/Cache/Region/DefaultRegion.php
-
- -
- message: '#^Method Doctrine\\ORM\\Cache\\Region\\DefaultRegion\:\:getCache\(\) should return Doctrine\\Common\\Cache\\CacheProvider but returns Doctrine\\Common\\Cache\\Cache\.$#'
- identifier: return.type
- count: 1
- path: src/Cache/Region/DefaultRegion.php
-
-
message: '#^Access to an undefined property Doctrine\\ORM\\Cache\\CacheEntry\:\:\$time\.$#'
identifier: property.notFound
count: 1
path: src/Cache/TimestampQueryCacheValidator.php
- -
- message: '#^Call to function method_exists\(\) with ''Doctrine\\\\DBAL\\\\Configuration'' and ''getResultCache'' will always evaluate to true\.$#'
- identifier: function.alreadyNarrowedType
- count: 1
- path: src/Configuration.php
-
- -
- message: '#^Call to function method_exists\(\) with ''Doctrine\\\\DBAL\\\\Configuration'' and ''setResultCache'' will always evaluate to true\.$#'
- identifier: function.alreadyNarrowedType
- count: 1
- path: src/Configuration.php
-
- -
- message: '#^Class Doctrine\\Common\\Cache\\ArrayCache not found\.$#'
- identifier: class.notFound
- count: 2
- path: src/Configuration.php
-
-
message: '#^Method Doctrine\\ORM\\Configuration\:\:getDefaultRepositoryClassName\(\) return type with generic class Doctrine\\ORM\\EntityRepository does not specify its types\: T$#'
identifier: missingType.generics
@@ -660,12 +528,6 @@ parameters:
count: 1
path: src/Configuration.php
- -
- message: '#^Parameter \#1 \$reader of class Doctrine\\ORM\\Mapping\\Driver\\AnnotationDriver constructor expects Doctrine\\Common\\Annotations\\Reader, Doctrine\\Common\\Annotations\\AnnotationReader\|Doctrine\\Common\\Annotations\\CachedReader\|Doctrine\\Common\\Annotations\\SimpleAnnotationReader given\.$#'
- identifier: argument.type
- count: 1
- path: src/Configuration.php
-
-
message: '#^Parameter \#2 \$className of method Doctrine\\ORM\\Configuration\:\:addCustomNumericFunction\(\) expects \(callable\(string\)\: Doctrine\\ORM\\Query\\AST\\Functions\\FunctionNode\)\|class\-string\, class\-string given\.$#'
identifier: argument.type
@@ -673,44 +535,26 @@ parameters:
path: src/Configuration.php
-
- message: '#^Call to function method_exists\(\) with Doctrine\\ORM\\EntityManagerInterface and ''wrapInTransaction'' will always evaluate to true\.$#'
- identifier: function.alreadyNarrowedType
- count: 1
- path: src/Decorator/EntityManagerDecorator.php
-
- -
- message: '#^Method Doctrine\\ORM\\Decorator\\EntityManagerDecorator\:\:find\(\) has parameter \$lockMode with no type specified\.$#'
- identifier: missingType.parameter
- count: 1
- path: src/Decorator/EntityManagerDecorator.php
-
- -
- message: '#^Method Doctrine\\ORM\\Decorator\\EntityManagerDecorator\:\:find\(\) has parameter \$lockVersion with no type specified\.$#'
- identifier: missingType.parameter
- count: 1
- path: src/Decorator/EntityManagerDecorator.php
-
- -
- message: '#^Method Doctrine\\ORM\\Decorator\\EntityManagerDecorator\:\:flush\(\) has parameter \$entity with no type specified\.$#'
- identifier: missingType.parameter
+ message: '#^Method Doctrine\\ORM\\Decorator\\EntityManagerDecorator\:\:getClassMetadata\(\) return type with generic class Doctrine\\ORM\\Mapping\\ClassMetadata does not specify its types\: T$#'
+ identifier: missingType.generics
count: 1
path: src/Decorator/EntityManagerDecorator.php
-
- message: '#^Method Doctrine\\ORM\\Decorator\\EntityManagerDecorator\:\:wrapInTransaction\(\) has no return type specified\.$#'
- identifier: missingType.return
+ message: '#^Method Doctrine\\ORM\\Decorator\\EntityManagerDecorator\:\:getRepository\(\) return type with generic class Doctrine\\ORM\\EntityRepository does not specify its types\: T$#'
+ identifier: missingType.generics
count: 1
path: src/Decorator/EntityManagerDecorator.php
-
- message: '#^Method Doctrine\\Persistence\\ObjectManager\:\:find\(\) invoked with 4 parameters, 2 required\.$#'
- identifier: arguments.count
+ message: '#^Return type \(Doctrine\\ORM\\Mapping\\ClassMetadataFactory\) of method Doctrine\\ORM\\Decorator\\EntityManagerDecorator\:\:getMetadataFactory\(\) should be compatible with return type \(Doctrine\\Persistence\\Mapping\\ClassMetadataFactory\\>\) of method Doctrine\\Persistence\\ObjectManager\:\:getMetadataFactory\(\)$#'
+ identifier: method.childReturnType
count: 1
path: src/Decorator/EntityManagerDecorator.php
-
- message: '#^Method Doctrine\\Persistence\\ObjectManager\:\:flush\(\) invoked with 1 parameter, 0 required\.$#'
- identifier: arguments.count
+ message: '#^Return type \(Doctrine\\ORM\\Mapping\\ClassMetadataFactory\) of method Doctrine\\ORM\\Decorator\\EntityManagerDecorator\:\:getMetadataFactory\(\) should be compatible with return type \(Doctrine\\Persistence\\Mapping\\ClassMetadataFactory\\>\) of method Doctrine\\Persistence\\ObjectManagerDecorator\\:\:getMetadataFactory\(\)$#'
+ identifier: method.childReturnType
count: 1
path: src/Decorator/EntityManagerDecorator.php
@@ -720,36 +564,6 @@ parameters:
count: 1
path: src/EntityManager.php
- -
- message: '#^Call to function is_callable\(\) with callable\(\)\: mixed will always evaluate to true\.$#'
- identifier: function.alreadyNarrowedType
- count: 1
- path: src/EntityManager.php
-
- -
- message: '#^Call to function is_object\(\) with \*NEVER\* will always evaluate to true\.$#'
- identifier: function.alreadyNarrowedType
- count: 1
- path: src/EntityManager.php
-
- -
- message: '#^Call to function is_object\(\) with object will always evaluate to true\.$#'
- identifier: function.alreadyNarrowedType
- count: 5
- path: src/EntityManager.php
-
- -
- message: '#^Call to function is_string\(\) with string will always evaluate to true\.$#'
- identifier: function.alreadyNarrowedType
- count: 1
- path: src/EntityManager.php
-
- -
- message: '#^Instanceof between Doctrine\\DBAL\\Connection and Doctrine\\DBAL\\Connection will always evaluate to true\.$#'
- identifier: instanceof.alwaysTrue
- count: 1
- path: src/EntityManager.php
-
-
message: '#^Method Doctrine\\ORM\\EntityManager\:\:checkLockRequirements\(\) has parameter \$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
identifier: missingType.generics
@@ -769,62 +583,26 @@ parameters:
path: src/EntityManager.php
-
- message: '#^Method Doctrine\\ORM\\EntityManager\:\:getPartialReference\(\) should return T\|null but returns object\.$#'
+ message: '#^Method Doctrine\\ORM\\EntityManager\:\:getReference\(\) should return \(T of object\)\|null but returns Doctrine\\ORM\\Proxy\\InternalProxy\.$#'
identifier: return.type
count: 1
path: src/EntityManager.php
-
- message: '#^Method Doctrine\\ORM\\EntityManager\:\:getPartialReference\(\) should return T\|null but returns object\|null\.$#'
+ message: '#^Method Doctrine\\ORM\\EntityManager\:\:getReference\(\) should return \(T of object\)\|null but returns object\|null\.$#'
identifier: return.type
count: 1
path: src/EntityManager.php
-
- message: '#^Method Doctrine\\ORM\\EntityManager\:\:getReference\(\) should return T\|null but returns Doctrine\\Common\\Proxy\\Proxy\.$#'
- identifier: return.type
- count: 1
- path: src/EntityManager.php
-
- -
- message: '#^Method Doctrine\\ORM\\EntityManager\:\:getReference\(\) should return T\|null but returns object\|null\.$#'
- identifier: return.type
- count: 2
- path: src/EntityManager.php
-
- -
- message: '#^Method Doctrine\\ORM\\EntityManager\:\:getRepository\(\) should return Doctrine\\ORM\\EntityRepository\ but returns Doctrine\\Persistence\\ObjectRepository\\.$#'
- identifier: return.type
- count: 1
- path: src/EntityManager.php
-
- -
- message: '#^Method Doctrine\\ORM\\EntityManager\:\:initializeObject\(\) has parameter \$obj with no type specified\.$#'
- identifier: missingType.parameter
- count: 1
- path: src/EntityManager.php
-
- -
- message: '#^Method Doctrine\\ORM\\EntityManager\:\:isUninitializedObject\(\) has parameter \$obj with no type specified\.$#'
- identifier: missingType.parameter
- count: 1
- path: src/EntityManager.php
-
- -
- message: '#^Method Doctrine\\ORM\\EntityManager\:\:wrapInTransaction\(\) has no return type specified\.$#'
- identifier: missingType.return
+ message: '#^Method Doctrine\\ORM\\EntityManager\:\:isUninitializedObject\(\) has parameter \$value with no type specified\.$#'
+ identifier: missingType.parameter
count: 1
path: src/EntityManager.php
-
message: '#^Parameter \#1 \$className of method Doctrine\\Persistence\\Mapping\\AbstractClassMetadataFactory\\:\:getMetadataFor\(\) expects class\-string, string given\.$#'
identifier: argument.type
- count: 2
- path: src/EntityManager.php
-
- -
- message: '#^Parameter \#1 \$modeName of method Doctrine\\ORM\\Configuration\:\:getCustomHydrationMode\(\) expects string, int\|string given\.$#'
- identifier: argument.type
count: 1
path: src/EntityManager.php
@@ -834,39 +612,33 @@ parameters:
count: 1
path: src/EntityManager.php
- -
- message: '#^Result of && is always false\.$#'
- identifier: booleanAnd.alwaysFalse
- count: 1
- path: src/EntityManager.php
-
-
message: '#^Return type \(Doctrine\\ORM\\Mapping\\ClassMetadataFactory\) of method Doctrine\\ORM\\EntityManager\:\:getMetadataFactory\(\) should be compatible with return type \(Doctrine\\Persistence\\Mapping\\ClassMetadataFactory\\>\) of method Doctrine\\Persistence\\ObjectManager\:\:getMetadataFactory\(\)$#'
identifier: method.childReturnType
- count: 2
+ count: 1
path: src/EntityManager.php
-
- message: '#^Unable to resolve the template type T in call to method Doctrine\\ORM\\EntityManager\:\:find\(\)$#'
- identifier: argument.templateType
+ message: '#^Return type \(Doctrine\\ORM\\Mapping\\ClassMetadataFactory\) of method Doctrine\\ORM\\EntityManagerInterface\:\:getMetadataFactory\(\) should be compatible with return type \(Doctrine\\Persistence\\Mapping\\ClassMetadataFactory\\>\) of method Doctrine\\Persistence\\ObjectManager\:\:getMetadataFactory\(\)$#'
+ identifier: method.childReturnType
count: 1
- path: src/EntityManager.php
+ path: src/EntityManagerInterface.php
-
- message: '#^Method Doctrine\\ORM\\EntityRepository\:\:findOneBy\(\) should return \(T of object\)\|null but returns object\|null\.$#'
+ message: '#^Method Doctrine\\ORM\\EntityRepository\:\:findBy\(\) should return list\ but returns array\\.$#'
identifier: return.type
count: 1
path: src/EntityRepository.php
-
- message: '#^Method Doctrine\\ORM\\EntityRepository\:\:matching\(\) should return Doctrine\\Common\\Collections\\AbstractLazyCollection\&Doctrine\\Common\\Collections\\Selectable\ but returns Doctrine\\ORM\\LazyCriteriaCollection\<\(int\|string\), object\>\.$#'
+ message: '#^Method Doctrine\\ORM\\EntityRepository\:\:findOneBy\(\) should return \(T of object\)\|null but returns object\|null\.$#'
identifier: return.type
count: 1
path: src/EntityRepository.php
-
- message: '#^Method Doctrine\\Persistence\\ObjectManager\:\:find\(\) invoked with 4 parameters, 2 required\.$#'
- identifier: arguments.count
+ message: '#^Method Doctrine\\ORM\\EntityRepository\:\:matching\(\) should return Doctrine\\Common\\Collections\\AbstractLazyCollection\&Doctrine\\Common\\Collections\\Selectable\ but returns Doctrine\\ORM\\LazyCriteriaCollection\<\(int\|string\), object\>\.$#'
+ identifier: return.type
count: 1
path: src/EntityRepository.php
@@ -919,26 +691,14 @@ parameters:
path: src/Event/PreUpdateEventArgs.php
-
- message: '#^Parameter \#1 \$className of method Doctrine\\ORM\\EntityManagerInterface\:\:getClassMetadata\(\) expects string, class\-string\|false given\.$#'
- identifier: argument.type
+ message: '#^Method Doctrine\\ORM\\Id\\AssignedGenerator\:\:generateId\(\) return type has no value type specified in iterable type array\.$#'
+ identifier: missingType.iterableValue
count: 1
path: src/Id/AssignedGenerator.php
-
- message: '#^Call to an undefined method Doctrine\\DBAL\\Platforms\\AbstractPlatform\:\:getTableHiLoCurrentValSql\(\)\.$#'
- identifier: method.notFound
- count: 1
- path: src/Id/TableGenerator.php
-
- -
- message: '#^Call to an undefined method Doctrine\\DBAL\\Platforms\\AbstractPlatform\:\:getTableHiLoUpdateNextValSql\(\)\.$#'
- identifier: method.notFound
- count: 1
- path: src/Id/TableGenerator.php
-
- -
- message: '#^Instanceof between Doctrine\\DBAL\\Driver\\ResultStatement and Doctrine\\DBAL\\Driver\\ResultStatement will always evaluate to true\.$#'
- identifier: instanceof.alwaysTrue
+ message: '#^Access to an undefined property Doctrine\\ORM\\Mapping\\ManyToManyInverseSideMapping\|Doctrine\\ORM\\Mapping\\ManyToManyOwningSideMapping\|Doctrine\\ORM\\Mapping\\ManyToOneAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToManyAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToOneInverseSideMapping\|Doctrine\\ORM\\Mapping\\OneToOneOwningSideMapping\:\:\$joinColumns\.$#'
+ identifier: property.notFound
count: 2
path: src/Internal/Hydration/AbstractHydrator.php
@@ -949,27 +709,27 @@ parameters:
path: src/Internal/Hydration/AbstractHydrator.php
-
- message: '#^Method Doctrine\\ORM\\Internal\\Hydration\\AbstractHydrator\:\:getClassMetadata\(\) return type with generic class Doctrine\\ORM\\Mapping\\ClassMetadata does not specify its types\: T$#'
+ message: '#^Method Doctrine\\ORM\\Internal\\Hydration\\AbstractHydrator\:\:gatherRowData\(\) return type with generic class ReflectionClass does not specify its types\: T$#'
identifier: missingType.generics
count: 1
path: src/Internal/Hydration/AbstractHydrator.php
-
- message: '#^Method Doctrine\\ORM\\Internal\\Hydration\\AbstractHydrator\:\:getDiscriminatorValues\(\) has parameter \$classMetadata with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
+ message: '#^Method Doctrine\\ORM\\Internal\\Hydration\\AbstractHydrator\:\:getClassMetadata\(\) return type with generic class Doctrine\\ORM\\Mapping\\ClassMetadata does not specify its types\: T$#'
identifier: missingType.generics
count: 1
path: src/Internal/Hydration/AbstractHydrator.php
-
- message: '#^Method Doctrine\\ORM\\Internal\\Hydration\\AbstractHydrator\:\:registerManaged\(\) has parameter \$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
+ message: '#^Method Doctrine\\ORM\\Internal\\Hydration\\AbstractHydrator\:\:getDiscriminatorValues\(\) has parameter \$classMetadata with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
identifier: missingType.generics
count: 1
path: src/Internal/Hydration/AbstractHydrator.php
-
- message: '#^Offset ''joinColumns'' might not exist on array\{cache\?\: array, cascade\: array\, declared\?\: class\-string, fetch\: mixed, fieldName\: string, id\?\: bool, inherited\?\: class\-string, indexBy\?\: string, \.\.\.\}\.$#'
- identifier: offsetAccess.notFound
- count: 2
+ message: '#^Method Doctrine\\ORM\\Internal\\Hydration\\AbstractHydrator\:\:registerManaged\(\) has parameter \$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
+ identifier: missingType.generics
+ count: 1
path: src/Internal/Hydration/AbstractHydrator.php
-
@@ -985,8 +745,8 @@ parameters:
path: src/Internal/Hydration/AbstractHydrator.php
-
- message: '#^Offset ''args'' might not exist on array\{class\: mixed, args\?\: array\}\.$#'
- identifier: offsetAccess.notFound
+ message: '#^Method Doctrine\\ORM\\Internal\\Hydration\\ArrayHydrator\:\:hydrateAllData\(\) return type has no value type specified in iterable type array\.$#'
+ identifier: missingType.iterableValue
count: 1
path: src/Internal/Hydration/ArrayHydrator.php
@@ -997,22 +757,28 @@ parameters:
path: src/Internal/Hydration/ArrayHydrator.php
-
- message: '#^Class Doctrine\\ORM\\Internal\\Hydration\\IterableResult implements generic interface Iterator but does not specify its types\: TKey, TValue$#'
- identifier: missingType.generics
- count: 1
- path: src/Internal/Hydration/IterableResult.php
+ message: '#^Access to an undefined property Doctrine\\ORM\\Mapping\\ManyToManyInverseSideMapping\|Doctrine\\ORM\\Mapping\\ManyToManyOwningSideMapping\|Doctrine\\ORM\\Mapping\\ManyToOneAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToManyAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToOneInverseSideMapping\|Doctrine\\ORM\\Mapping\\OneToOneOwningSideMapping\:\:\$inversedBy\.$#'
+ identifier: property.notFound
+ count: 2
+ path: src/Internal/Hydration/ObjectHydrator.php
-
- message: '#^Property Doctrine\\ORM\\Internal\\Hydration\\IterableResult\:\:\$current \(array\\|null\) does not accept array\\|false\.$#'
- identifier: assign.propertyType
+ message: '#^Access to an undefined property Doctrine\\ORM\\Mapping\\ManyToManyInverseSideMapping\|Doctrine\\ORM\\Mapping\\ManyToManyOwningSideMapping\|Doctrine\\ORM\\Mapping\\ManyToOneAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToManyAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToOneInverseSideMapping\|Doctrine\\ORM\\Mapping\\OneToOneOwningSideMapping\:\:\$joinColumns\.$#'
+ identifier: property.notFound
count: 2
- path: src/Internal/Hydration/IterableResult.php
+ path: src/Internal/Hydration/ObjectHydrator.php
-
- message: '#^Strict comparison using \!\=\= between array\\|null and false will always evaluate to true\.$#'
- identifier: notIdentical.alwaysTrue
+ message: '#^Access to an undefined property Doctrine\\ORM\\Mapping\\ManyToManyInverseSideMapping\|Doctrine\\ORM\\Mapping\\ManyToManyOwningSideMapping\|Doctrine\\ORM\\Mapping\\ManyToOneAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToManyAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToOneInverseSideMapping\|Doctrine\\ORM\\Mapping\\OneToOneOwningSideMapping\:\:\$mappedBy\.$#'
+ identifier: property.notFound
+ count: 3
+ path: src/Internal/Hydration/ObjectHydrator.php
+
+ -
+ message: '#^Method Doctrine\\ORM\\Internal\\Hydration\\ObjectHydrator\:\:hydrateAllData\(\) return type has no value type specified in iterable type array\.$#'
+ identifier: missingType.iterableValue
count: 1
- path: src/Internal/Hydration/IterableResult.php
+ path: src/Internal/Hydration/ObjectHydrator.php
-
message: '#^Method Doctrine\\ORM\\Internal\\Hydration\\ObjectHydrator\:\:initRelatedCollection\(\) has parameter \$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
@@ -1027,23 +793,35 @@ parameters:
path: src/Internal/Hydration/ObjectHydrator.php
-
- message: '#^Offset ''args'' might not exist on array\{class\: mixed, args\?\: array\}\.$#'
- identifier: offsetAccess.notFound
+ message: '#^Parameter \#2 \$assoc of method Doctrine\\ORM\\PersistentCollection\<\(int\|string\),mixed\>\:\:setOwner\(\) expects Doctrine\\ORM\\Mapping\\AssociationMapping&Doctrine\\ORM\\Mapping\\ToManyAssociationMapping, Doctrine\\ORM\\Mapping\\ManyToManyInverseSideMapping\|Doctrine\\ORM\\Mapping\\ManyToManyOwningSideMapping\|Doctrine\\ORM\\Mapping\\ManyToOneAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToManyAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToOneInverseSideMapping\|Doctrine\\ORM\\Mapping\\OneToOneOwningSideMapping given\.$#'
+ identifier: argument.type
count: 1
path: src/Internal/Hydration/ObjectHydrator.php
- -
- message: '#^Offset ''joinColumns'' might not exist on array\{cache\?\: array, cascade\: array\, declared\?\: class\-string, fetch\: mixed, fieldName\: string, id\?\: bool, inherited\?\: class\-string, indexBy\?\: string, \.\.\.\}\.$#'
- identifier: offsetAccess.notFound
- count: 2
- path: src/Internal/Hydration/ObjectHydrator.php
-
-
message: '#^Property Doctrine\\ORM\\Internal\\Hydration\\ObjectHydrator\:\:\$uninitializedCollections with generic class Doctrine\\ORM\\PersistentCollection does not specify its types\: TKey, T$#'
identifier: missingType.generics
count: 1
path: src/Internal/Hydration/ObjectHydrator.php
+ -
+ message: '#^Method Doctrine\\ORM\\Internal\\Hydration\\ScalarColumnHydrator\:\:hydrateAllData\(\) return type has no value type specified in iterable type array\.$#'
+ identifier: missingType.iterableValue
+ count: 1
+ path: src/Internal/Hydration/ScalarColumnHydrator.php
+
+ -
+ message: '#^Method Doctrine\\ORM\\Internal\\Hydration\\ScalarHydrator\:\:hydrateAllData\(\) return type has no value type specified in iterable type array\.$#'
+ identifier: missingType.iterableValue
+ count: 1
+ path: src/Internal/Hydration/ScalarHydrator.php
+
+ -
+ message: '#^Method Doctrine\\ORM\\Internal\\Hydration\\SimpleObjectHydrator\:\:hydrateAllData\(\) return type has no value type specified in iterable type array\.$#'
+ identifier: missingType.iterableValue
+ count: 1
+ path: src/Internal/Hydration/SimpleObjectHydrator.php
+
-
message: '#^Property Doctrine\\ORM\\Internal\\Hydration\\SimpleObjectHydrator\:\:\$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata does not specify its types\: T$#'
identifier: missingType.generics
@@ -1092,12 +870,6 @@ parameters:
count: 1
path: src/Mapping/AnsiQuoteStrategy.php
- -
- message: '#^Method Doctrine\\ORM\\Mapping\\AnsiQuoteStrategy\:\:getJoinTableName\(\) has parameter \$association with no value type specified in iterable type array\.$#'
- identifier: missingType.iterableValue
- count: 5
- path: src/Mapping/AnsiQuoteStrategy.php
-
-
message: '#^Method Doctrine\\ORM\\Mapping\\AnsiQuoteStrategy\:\:getJoinTableName\(\) has parameter \$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
identifier: missingType.generics
@@ -1123,16 +895,16 @@ parameters:
path: src/Mapping/AnsiQuoteStrategy.php
-
- message: '#^Offset ''joinTable'' might not exist on array\{cache\?\: array, cascade\: array\, declared\?\: class\-string, fetch\: mixed, fieldName\: string, id\?\: bool, inherited\?\: class\-string, indexBy\?\: string, \.\.\.\}\.$#'
- identifier: offsetAccess.notFound
+ message: '#^Parameter \#1 \$mappingArray of static method Doctrine\\ORM\\Mapping\\JoinTableMapping\:\:fromMappingArray\(\) expects array\{name\: string, quoted\?\: bool\|null, joinColumns\?\: array\, inverseJoinColumns\?\: array\, schema\?\: string\|null, options\?\: array\\}, non\-empty\-array\ given\.$#'
+ identifier: argument.type
count: 1
- path: src/Mapping/AnsiQuoteStrategy.php
+ path: src/Mapping/AssociationMapping.php
-
- message: '#^@readonly property cannot have a default value\.$#'
- identifier: property.readOnlyByPhpDocDefaultValue
+ message: '#^Property Doctrine\\ORM\\Mapping\\AssociationMapping\:\:\$cache type has no value type specified in iterable type array\.$#'
+ identifier: missingType.iterableValue
count: 1
- path: src/Mapping/AssociationOverrides.php
+ path: src/Mapping/AssociationMapping.php
-
message: '#^Instanceof between Doctrine\\ORM\\Mapping\\AssociationOverride and Doctrine\\ORM\\Mapping\\AssociationOverride will always evaluate to true\.$#'
@@ -1140,12 +912,6 @@ parameters:
count: 1
path: src/Mapping/AssociationOverrides.php
- -
- message: '#^@readonly property cannot have a default value\.$#'
- identifier: property.readOnlyByPhpDocDefaultValue
- count: 1
- path: src/Mapping/AttributeOverrides.php
-
-
message: '#^Instanceof between Doctrine\\ORM\\Mapping\\AttributeOverride and Doctrine\\ORM\\Mapping\\AttributeOverride will always evaluate to true\.$#'
identifier: instanceof.alwaysTrue
@@ -1153,28 +919,28 @@ parameters:
path: src/Mapping/AttributeOverrides.php
-
- message: '#^Method Doctrine\\ORM\\Mapping\\Builder\\ClassMetadataBuilder\:\:__construct\(\) has parameter \$cm with generic class Doctrine\\ORM\\Mapping\\ClassMetadataInfo but does not specify its types\: T$#'
+ message: '#^Method Doctrine\\ORM\\Mapping\\Builder\\ClassMetadataBuilder\:\:__construct\(\) has parameter \$cm with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
identifier: missingType.generics
count: 1
path: src/Mapping/Builder/ClassMetadataBuilder.php
-
- message: '#^Method Doctrine\\ORM\\Mapping\\Builder\\ClassMetadataBuilder\:\:getClassMetadata\(\) return type with generic class Doctrine\\ORM\\Mapping\\ClassMetadataInfo does not specify its types\: T$#'
+ message: '#^Method Doctrine\\ORM\\Mapping\\Builder\\ClassMetadataBuilder\:\:getClassMetadata\(\) return type with generic class Doctrine\\ORM\\Mapping\\ClassMetadata does not specify its types\: T$#'
identifier: missingType.generics
count: 1
path: src/Mapping/Builder/ClassMetadataBuilder.php
-
- message: '#^Parameter \#1 \$repositoryClassName of method Doctrine\\ORM\\Mapping\\ClassMetadataInfo\