diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml
index b352a21538b..73bec1912e1 100644
--- a/.github/workflows/coding-standards.yml
+++ b/.github/workflows/coding-standards.yml
@@ -24,4 +24,4 @@ on:
jobs:
coding-standards:
- uses: "doctrine/.github/.github/workflows/coding-standards.yml@v12.2.0"
+ uses: "doctrine/.github/.github/workflows/coding-standards.yml@13.0.0"
diff --git a/.github/workflows/composer-lint.yml b/.github/workflows/composer-lint.yml
index 2b141c2b23f..9290eafb3fb 100644
--- a/.github/workflows/composer-lint.yml
+++ b/.github/workflows/composer-lint.yml
@@ -17,4 +17,4 @@ on:
jobs:
composer-lint:
name: "Composer Lint"
- uses: "doctrine/.github/.github/workflows/composer-lint.yml@v12.2.0"
+ uses: "doctrine/.github/.github/workflows/composer-lint.yml@13.0.0"
diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index cec65243d48..c70beb6769f 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -65,7 +65,7 @@ jobs:
steps:
- name: "Checkout"
- uses: "actions/checkout@v5"
+ uses: "actions/checkout@v6"
with:
fetch-depth: 2
@@ -149,7 +149,7 @@ jobs:
steps:
- name: "Checkout"
- uses: "actions/checkout@v5"
+ uses: "actions/checkout@v6"
with:
fetch-depth: 2
@@ -221,7 +221,7 @@ jobs:
steps:
- name: "Checkout"
- uses: "actions/checkout@v5"
+ uses: "actions/checkout@v6"
with:
fetch-depth: 2
@@ -293,7 +293,7 @@ jobs:
steps:
- name: "Checkout"
- uses: "actions/checkout@v5"
+ uses: "actions/checkout@v6"
with:
fetch-depth: 2
@@ -345,7 +345,7 @@ jobs:
steps:
- name: "Checkout"
- uses: "actions/checkout@v5"
+ uses: "actions/checkout@v6"
with:
fetch-depth: 2
@@ -377,7 +377,7 @@ jobs:
steps:
- name: "Checkout"
- uses: "actions/checkout@v5"
+ uses: "actions/checkout@v6"
with:
fetch-depth: 2
diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml
index f99319c4b49..6825494ccff 100644
--- a/.github/workflows/documentation.yml
+++ b/.github/workflows/documentation.yml
@@ -17,4 +17,4 @@ on:
jobs:
documentation:
name: "Documentation"
- uses: "doctrine/.github/.github/workflows/documentation.yml@v12.2.0"
+ uses: "doctrine/.github/.github/workflows/documentation.yml@13.0.0"
diff --git a/.github/workflows/phpbench.yml b/.github/workflows/phpbench.yml
index af699ff5644..aff9a88c999 100644
--- a/.github/workflows/phpbench.yml
+++ b/.github/workflows/phpbench.yml
@@ -36,7 +36,7 @@ jobs:
steps:
- name: "Checkout"
- uses: "actions/checkout@v5"
+ uses: "actions/checkout@v6"
with:
fetch-depth: 2
diff --git a/.github/workflows/release-on-milestone-closed.yml b/.github/workflows/release-on-milestone-closed.yml
index 4e1786168e6..ad5c658d9c7 100644
--- a/.github/workflows/release-on-milestone-closed.yml
+++ b/.github/workflows/release-on-milestone-closed.yml
@@ -7,7 +7,7 @@ on:
jobs:
release:
- uses: "doctrine/.github/.github/workflows/release-on-milestone-closed.yml@v12.2.0"
+ uses: "doctrine/.github/.github/workflows/release-on-milestone-closed.yml@13.0.0"
secrets:
GIT_AUTHOR_EMAIL: ${{ secrets.GIT_AUTHOR_EMAIL }}
GIT_AUTHOR_NAME: ${{ secrets.GIT_AUTHOR_NAME }}
diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
index 1462df991ba..e949b69d27a 100644
--- a/.github/workflows/static-analysis.yml
+++ b/.github/workflows/static-analysis.yml
@@ -40,7 +40,7 @@ jobs:
steps:
- name: "Checkout code"
- uses: "actions/checkout@v5"
+ uses: "actions/checkout@v6"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
diff --git a/composer.json b/composer.json
index ccf22b1f1a7..15c95c45219 100644
--- a/composer.json
+++ b/composer.json
@@ -45,7 +45,7 @@
"doctrine/lexer": "^2 || ^3",
"doctrine/persistence": "^2.4 || ^3",
"psr/cache": "^1 || ^2 || ^3",
- "symfony/console": "^4.2 || ^5.0 || ^6.0 || ^7.0",
+ "symfony/console": "^4.2 || ^5.0 || ^6.0 || ^7.0 || ^8.0",
"symfony/polyfill-php72": "^1.23",
"symfony/polyfill-php80": "^1.16"
},
@@ -60,7 +60,7 @@
"psr/log": "^1 || ^2 || ^3",
"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"
+ "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0"
},
"conflict": {
"doctrine/annotations": "<1.13 || >= 3.0"
diff --git a/docs/en/reference/basic-mapping.rst b/docs/en/reference/basic-mapping.rst
index 0070c271762..ca0d7b45d9c 100644
--- a/docs/en/reference/basic-mapping.rst
+++ b/docs/en/reference/basic-mapping.rst
@@ -254,6 +254,21 @@ Here is a complete list of ``Column``s attributes (all optional):
- ``options``: Key-value pairs of options that get passed
to the underlying database platform when generating DDL statements.
+Specifying default values
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+While it is possible to specify default values for properties in your
+PHP class, Doctrine also allows you to specify default values for
+database columns using the ``default`` key in the ``options`` array of
+the ``Column`` attribute.
+
+.. configuration-block::
+ .. literalinclude:: basic-mapping/DefaultValues.php
+ :language: attribute
+
+ .. literalinclude:: basic-mapping/default-values.xml
+ :language: xml
+
.. _reference-php-mapping-types:
PHP Types Mapping
diff --git a/docs/en/reference/basic-mapping/DefaultValues.php b/docs/en/reference/basic-mapping/DefaultValues.php
new file mode 100644
index 00000000000..e702f5bdd14
--- /dev/null
+++ b/docs/en/reference/basic-mapping/DefaultValues.php
@@ -0,0 +1,15 @@
+ 'Hello World!'])]
+ private string $text;
+}
diff --git a/docs/en/reference/basic-mapping/default-values.xml b/docs/en/reference/basic-mapping/default-values.xml
new file mode 100644
index 00000000000..2671080a9e4
--- /dev/null
+++ b/docs/en/reference/basic-mapping/default-values.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/docs/en/reference/faq.rst b/docs/en/reference/faq.rst
index 85b6e35d851..2fa1b88c1c3 100644
--- a/docs/en/reference/faq.rst
+++ b/docs/en/reference/faq.rst
@@ -18,30 +18,6 @@ In your mapping configuration, the column definition (for example, the
the ``charset`` and ``collation``. The default values are ``utf8`` and
``utf8_unicode_ci``, respectively.
-Entity Classes
---------------
-
-How can I add default values to a column?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Doctrine does not support to set the default values in columns through the "DEFAULT" keyword in SQL.
-This is not necessary however, you can just use your class properties as default values. These are then used
-upon insert:
-
-.. code-block:: php
-
- class User
- {
- private const STATUS_DISABLED = 0;
- private const STATUS_ENABLED = 1;
-
- private string $algorithm = "sha1";
- /** @var self::STATUS_* */
- private int $status = self::STATUS_DISABLED;
- }
-
-.
-
Mapping
-------
diff --git a/src/Configuration.php b/src/Configuration.php
index 4fb237260ce..2aa86b4ba33 100644
--- a/src/Configuration.php
+++ b/src/Configuration.php
@@ -1113,7 +1113,7 @@ public function setLazyGhostObjectEnabled(bool $flag): void
if ($flag && ! trait_exists(LazyGhostTrait::class)) {
throw new LogicException(
'Lazy ghost objects cannot be enabled because the "symfony/var-exporter" library'
- . ' version 6.2 or higher is not installed. Please run "composer require symfony/var-exporter:^6.2".'
+ . ' version 6.2 or 7 is not installed. Please run "composer require symfony/var-exporter:^6.4".'
);
}
diff --git a/src/Tools/Console/ApplicationCompatibility.php b/src/Tools/Console/ApplicationCompatibility.php
index 71b2ecf10fd..3f7f90bc617 100644
--- a/src/Tools/Console/ApplicationCompatibility.php
+++ b/src/Tools/Console/ApplicationCompatibility.php
@@ -18,11 +18,12 @@ trait ApplicationCompatibility
{
private static function addCommandToApplication(Application $application, Command $command): ?Command
{
+ // @phpstan-ignore function.alreadyNarrowedType (This method did not exist before Symfony 7.4)
if (method_exists(Application::class, 'addCommand')) {
- // @phpstan-ignore method.notFound (This method will be added in Symfony 7.4)
return $application->addCommand($command);
}
+ // @phpstan-ignore method.notFound
return $application->add($command);
}
}
diff --git a/src/Tools/Console/Command/ClearCache/CollectionRegionCommand.php b/src/Tools/Console/Command/ClearCache/CollectionRegionCommand.php
index 84e911f171b..70fa324a317 100644
--- a/src/Tools/Console/Command/ClearCache/CollectionRegionCommand.php
+++ b/src/Tools/Console/Command/ClearCache/CollectionRegionCommand.php
@@ -23,8 +23,7 @@ class CollectionRegionCommand extends AbstractEntityManagerCommand
{
use CommandCompatibility;
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName('orm:clear-cache:region:collection')
->setDescription('Clear a second-level cache collection region')
diff --git a/src/Tools/Console/Command/ClearCache/EntityRegionCommand.php b/src/Tools/Console/Command/ClearCache/EntityRegionCommand.php
index 51d08946521..e55f1c310b2 100644
--- a/src/Tools/Console/Command/ClearCache/EntityRegionCommand.php
+++ b/src/Tools/Console/Command/ClearCache/EntityRegionCommand.php
@@ -23,8 +23,7 @@ class EntityRegionCommand extends AbstractEntityManagerCommand
{
use CommandCompatibility;
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName('orm:clear-cache:region:entity')
->setDescription('Clear a second-level cache entity region')
diff --git a/src/Tools/Console/Command/ClearCache/MetadataCommand.php b/src/Tools/Console/Command/ClearCache/MetadataCommand.php
index 96decbc50a9..bb365bc3c04 100644
--- a/src/Tools/Console/Command/ClearCache/MetadataCommand.php
+++ b/src/Tools/Console/Command/ClearCache/MetadataCommand.php
@@ -21,8 +21,7 @@ class MetadataCommand extends AbstractEntityManagerCommand
{
use CommandCompatibility;
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName('orm:clear-cache:metadata')
->setDescription('Clear all metadata cache of the various cache drivers')
diff --git a/src/Tools/Console/Command/ClearCache/QueryCommand.php b/src/Tools/Console/Command/ClearCache/QueryCommand.php
index 06f76dcfaa4..7fc579be598 100644
--- a/src/Tools/Console/Command/ClearCache/QueryCommand.php
+++ b/src/Tools/Console/Command/ClearCache/QueryCommand.php
@@ -30,8 +30,7 @@ class QueryCommand extends AbstractEntityManagerCommand
{
use CommandCompatibility;
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName('orm:clear-cache:query')
->setDescription('Clear all query cache of the various cache drivers')
diff --git a/src/Tools/Console/Command/ClearCache/QueryRegionCommand.php b/src/Tools/Console/Command/ClearCache/QueryRegionCommand.php
index faca872e0f1..d9bfa9be5b8 100644
--- a/src/Tools/Console/Command/ClearCache/QueryRegionCommand.php
+++ b/src/Tools/Console/Command/ClearCache/QueryRegionCommand.php
@@ -23,8 +23,7 @@ class QueryRegionCommand extends AbstractEntityManagerCommand
{
use CommandCompatibility;
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName('orm:clear-cache:region:query')
->setDescription('Clear a second-level cache query region')
diff --git a/src/Tools/Console/Command/ClearCache/ResultCommand.php b/src/Tools/Console/Command/ClearCache/ResultCommand.php
index b61a55e0fe7..73c60802d32 100644
--- a/src/Tools/Console/Command/ClearCache/ResultCommand.php
+++ b/src/Tools/Console/Command/ClearCache/ResultCommand.php
@@ -32,8 +32,7 @@ class ResultCommand extends AbstractEntityManagerCommand
{
use CommandCompatibility;
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName('orm:clear-cache:result')
->setDescription('Clear all result cache of the various cache drivers')
diff --git a/src/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php b/src/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php
index df0d42dc702..7aa09db3cca 100644
--- a/src/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php
+++ b/src/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php
@@ -75,8 +75,7 @@ public function setMetadataExporter(ClassMetadataExporter $metadataExporter)
$this->metadataExporter = $metadataExporter;
}
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName('orm:convert-d1-schema')
->setAliases(['orm:convert:d1-schema'])
diff --git a/src/Tools/Console/Command/ConvertMappingCommand.php b/src/Tools/Console/Command/ConvertMappingCommand.php
index f3bdea25f14..a95ca547fad 100644
--- a/src/Tools/Console/Command/ConvertMappingCommand.php
+++ b/src/Tools/Console/Command/ConvertMappingCommand.php
@@ -40,8 +40,7 @@ class ConvertMappingCommand extends AbstractEntityManagerCommand
{
use CommandCompatibility;
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName('orm:convert-mapping')
->setAliases(['orm:convert:mapping'])
diff --git a/src/Tools/Console/Command/EnsureProductionSettingsCommand.php b/src/Tools/Console/Command/EnsureProductionSettingsCommand.php
index bb5df1637a4..2d8ecfe5ddb 100644
--- a/src/Tools/Console/Command/EnsureProductionSettingsCommand.php
+++ b/src/Tools/Console/Command/EnsureProductionSettingsCommand.php
@@ -22,8 +22,7 @@ class EnsureProductionSettingsCommand extends AbstractEntityManagerCommand
{
use CommandCompatibility;
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName('orm:ensure-production-settings')
->setDescription('Verify that Doctrine is properly configured for a production environment')
diff --git a/src/Tools/Console/Command/GenerateEntitiesCommand.php b/src/Tools/Console/Command/GenerateEntitiesCommand.php
index 7fdcb98bc8e..c7f2eb44505 100644
--- a/src/Tools/Console/Command/GenerateEntitiesCommand.php
+++ b/src/Tools/Console/Command/GenerateEntitiesCommand.php
@@ -31,8 +31,7 @@ class GenerateEntitiesCommand extends AbstractEntityManagerCommand
{
use CommandCompatibility;
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName('orm:generate-entities')
->setAliases(['orm:generate:entities'])
diff --git a/src/Tools/Console/Command/GenerateProxiesCommand.php b/src/Tools/Console/Command/GenerateProxiesCommand.php
index 6a602869857..da7ee8f69df 100644
--- a/src/Tools/Console/Command/GenerateProxiesCommand.php
+++ b/src/Tools/Console/Command/GenerateProxiesCommand.php
@@ -29,8 +29,7 @@ class GenerateProxiesCommand extends AbstractEntityManagerCommand
{
use CommandCompatibility;
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName('orm:generate-proxies')
->setAliases(['orm:generate:proxies'])
diff --git a/src/Tools/Console/Command/GenerateRepositoriesCommand.php b/src/Tools/Console/Command/GenerateRepositoriesCommand.php
index 54379d5f6b7..539f4e8073a 100644
--- a/src/Tools/Console/Command/GenerateRepositoriesCommand.php
+++ b/src/Tools/Console/Command/GenerateRepositoriesCommand.php
@@ -30,8 +30,7 @@ class GenerateRepositoriesCommand extends AbstractEntityManagerCommand
{
use CommandCompatibility;
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName('orm:generate-repositories')
->setAliases(['orm:generate:repositories'])
diff --git a/src/Tools/Console/Command/InfoCommand.php b/src/Tools/Console/Command/InfoCommand.php
index 9b232efbb50..2be5c1da147 100644
--- a/src/Tools/Console/Command/InfoCommand.php
+++ b/src/Tools/Console/Command/InfoCommand.php
@@ -23,8 +23,7 @@ class InfoCommand extends AbstractEntityManagerCommand
{
use CommandCompatibility;
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName('orm:info')
->setDescription('Show basic information about all mapped entities')
diff --git a/src/Tools/Console/Command/RunDqlCommand.php b/src/Tools/Console/Command/RunDqlCommand.php
index 61f1eef78f1..9bc79d684a6 100644
--- a/src/Tools/Console/Command/RunDqlCommand.php
+++ b/src/Tools/Console/Command/RunDqlCommand.php
@@ -30,8 +30,7 @@ class RunDqlCommand extends AbstractEntityManagerCommand
{
use CommandCompatibility;
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName('orm:run-dql')
->setDescription('Executes arbitrary DQL directly from the command line')
diff --git a/src/Tools/Console/Command/SchemaTool/AbstractCommand.php b/src/Tools/Console/Command/SchemaTool/AbstractCommand.php
index cabf90759a7..c269068089f 100644
--- a/src/Tools/Console/Command/SchemaTool/AbstractCommand.php
+++ b/src/Tools/Console/Command/SchemaTool/AbstractCommand.php
@@ -27,6 +27,10 @@ abstract class AbstractCommand extends AbstractEntityManagerCommand
*/
abstract protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui);
+ private function doConfigure(): void
+ {
+ }
+
private function doExecute(InputInterface $input, OutputInterface $output): int
{
$ui = new SymfonyStyle($input, $output);
diff --git a/src/Tools/Console/Command/SchemaTool/CreateCommand.php b/src/Tools/Console/Command/SchemaTool/CreateCommand.php
index 2438d4109f0..85e0562246f 100644
--- a/src/Tools/Console/Command/SchemaTool/CreateCommand.php
+++ b/src/Tools/Console/Command/SchemaTool/CreateCommand.php
@@ -4,6 +4,7 @@
namespace Doctrine\ORM\Tools\Console\Command\SchemaTool;
+use Doctrine\ORM\Tools\Console\CommandCompatibility;
use Doctrine\ORM\Tools\SchemaTool;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -19,8 +20,9 @@
*/
class CreateCommand extends AbstractCommand
{
- /** @return void */
- protected function configure()
+ use CommandCompatibility;
+
+ private function doConfigure(): void
{
$this->setName('orm:schema-tool:create')
->setDescription('Processes the schema and either create it directly on EntityManager Storage Connection or generate the SQL output')
@@ -44,6 +46,11 @@ protected function configure()
);
}
+ private function doExecute(InputInterface $input, OutputInterface $output): int
+ {
+ return parent::execute($input, $output);
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/src/Tools/Console/Command/SchemaTool/DropCommand.php b/src/Tools/Console/Command/SchemaTool/DropCommand.php
index c312675392d..531fde66e8c 100644
--- a/src/Tools/Console/Command/SchemaTool/DropCommand.php
+++ b/src/Tools/Console/Command/SchemaTool/DropCommand.php
@@ -4,6 +4,7 @@
namespace Doctrine\ORM\Tools\Console\Command\SchemaTool;
+use Doctrine\ORM\Tools\Console\CommandCompatibility;
use Doctrine\ORM\Tools\SchemaTool;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -20,8 +21,9 @@
*/
class DropCommand extends AbstractCommand
{
- /** @return void */
- protected function configure()
+ use CommandCompatibility;
+
+ private function doConfigure(): void
{
$this->setName('orm:schema-tool:drop')
->setDescription('Drop the complete database schema of EntityManager Storage Connection or generate the corresponding SQL output')
@@ -48,6 +50,11 @@ protected function configure()
);
}
+ private function doExecute(InputInterface $input, OutputInterface $output): int
+ {
+ return parent::execute($input, $output);
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/src/Tools/Console/Command/SchemaTool/UpdateCommand.php b/src/Tools/Console/Command/SchemaTool/UpdateCommand.php
index 3d2631ec0f7..15667bc299c 100644
--- a/src/Tools/Console/Command/SchemaTool/UpdateCommand.php
+++ b/src/Tools/Console/Command/SchemaTool/UpdateCommand.php
@@ -4,6 +4,7 @@
namespace Doctrine\ORM\Tools\Console\Command\SchemaTool;
+use Doctrine\ORM\Tools\Console\CommandCompatibility;
use Doctrine\ORM\Tools\SchemaTool;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -21,11 +22,12 @@
*/
class UpdateCommand extends AbstractCommand
{
+ use CommandCompatibility;
+
/** @var string */
protected $name = 'orm:schema-tool:update';
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName($this->name)
->setDescription('Executes (or dumps) the SQL needed to update the database schema to match the current mapping metadata')
@@ -72,6 +74,11 @@ protected function configure()
);
}
+ private function doExecute(InputInterface $input, OutputInterface $output): int
+ {
+ return parent::execute($input, $output);
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/src/Tools/Console/Command/ValidateSchemaCommand.php b/src/Tools/Console/Command/ValidateSchemaCommand.php
index 3807a81d58d..78feaec2ab8 100644
--- a/src/Tools/Console/Command/ValidateSchemaCommand.php
+++ b/src/Tools/Console/Command/ValidateSchemaCommand.php
@@ -23,8 +23,7 @@ class ValidateSchemaCommand extends AbstractEntityManagerCommand
{
use CommandCompatibility;
- /** @return void */
- protected function configure()
+ private function doConfigure(): void
{
$this->setName('orm:validate-schema')
->setDescription('Validate the mapping files')
diff --git a/src/Tools/Console/CommandCompatibility.php b/src/Tools/Console/CommandCompatibility.php
index 4e16698f5d2..e13cb79cfed 100644
--- a/src/Tools/Console/CommandCompatibility.php
+++ b/src/Tools/Console/CommandCompatibility.php
@@ -9,10 +9,32 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
-if ((new ReflectionMethod(Command::class, 'execute'))->hasReturnType()) {
+// Symfony 8
+if ((new ReflectionMethod(Command::class, 'configure'))->hasReturnType()) {
/** @internal */
trait CommandCompatibility
{
+ protected function configure(): void
+ {
+ $this->doConfigure();
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ return $this->doExecute($input, $output);
+ }
+ }
+// Symfony 7
+} elseif ((new ReflectionMethod(Command::class, 'execute'))->hasReturnType()) {
+ /** @internal */
+ trait CommandCompatibility
+ {
+ /** @return void */
+ protected function configure()
+ {
+ $this->doConfigure();
+ }
+
protected function execute(InputInterface $input, OutputInterface $output): int
{
return $this->doExecute($input, $output);
@@ -22,6 +44,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
/** @internal */
trait CommandCompatibility
{
+ /** @return void */
+ protected function configure()
+ {
+ $this->doConfigure();
+ }
+
/**
* {@inheritDoc}
*
diff --git a/src/UnitOfWork.php b/src/UnitOfWork.php
index 0b80702a80e..bf84ca01f93 100644
--- a/src/UnitOfWork.php
+++ b/src/UnitOfWork.php
@@ -62,6 +62,7 @@
use function array_sum;
use function array_values;
use function assert;
+use function count;
use function current;
use function func_get_arg;
use function func_num_args;
@@ -3172,8 +3173,14 @@ public function createEntity($className, array $data, &$hints = [])
$reflField->setValue($entity, $pColl);
if ($hints['fetchMode'][$class->name][$field] === ClassMetadata::FETCH_EAGER) {
- $isIteration = isset($hints[Query::HINT_INTERNAL_ITERATION]) && $hints[Query::HINT_INTERNAL_ITERATION];
- if ($assoc['type'] === ClassMetadata::ONE_TO_MANY && ! $isIteration && ! $targetClass->isIdentifierComposite && ! isset($assoc['indexBy'])) {
+ if (
+ $assoc['type'] === ClassMetadata::ONE_TO_MANY
+ // is iteration
+ && ! (isset($hints[Query::HINT_INTERNAL_ITERATION]) && $hints[Query::HINT_INTERNAL_ITERATION])
+ // is foreign key composite
+ && ! ($targetClass->hasAssociation($assoc['mappedBy']) && count($targetClass->getAssociationMapping($assoc['mappedBy'])['joinColumns'] ?? []) > 1)
+ && ! isset($assoc['indexBy'])
+ ) {
$this->scheduleCollectionForBatchLoading($pColl, $class);
} else {
$this->loadCollection($pColl);
diff --git a/tests/Tests/Models/EagerFetchedCompositeOneToMany/RootEntity.php b/tests/Tests/Models/EagerFetchedCompositeOneToMany/RootEntity.php
index af16c686970..c804c90369c 100644
--- a/tests/Tests/Models/EagerFetchedCompositeOneToMany/RootEntity.php
+++ b/tests/Tests/Models/EagerFetchedCompositeOneToMany/RootEntity.php
@@ -37,11 +37,19 @@ class RootEntity
*/
private $secondLevel;
+ /**
+ * @ORM\OneToMany(mappedBy="root", targetEntity=SecondLevelWithoutCompositePrimaryKey::class, fetch="EAGER")
+ *
+ * @var Collection
+ */
+ private $anotherSecondLevel;
+
public function __construct(int $id, string $other)
{
- $this->otherKey = $other;
- $this->secondLevel = new ArrayCollection();
- $this->id = $id;
+ $this->otherKey = $other;
+ $this->secondLevel = new ArrayCollection();
+ $this->anotherSecondLevel = new ArrayCollection();
+ $this->id = $id;
}
public function getId(): ?int
diff --git a/tests/Tests/Models/EagerFetchedCompositeOneToMany/SecondLevelWithoutCompositePrimaryKey.php b/tests/Tests/Models/EagerFetchedCompositeOneToMany/SecondLevelWithoutCompositePrimaryKey.php
new file mode 100644
index 00000000000..323ac52060a
--- /dev/null
+++ b/tests/Tests/Models/EagerFetchedCompositeOneToMany/SecondLevelWithoutCompositePrimaryKey.php
@@ -0,0 +1,43 @@
+root = $upper;
+ }
+
+ public function getId(): ?int
+ {
+ return $this->id;
+ }
+}
diff --git a/tests/Tests/ORM/Functional/EagerFetchOneToManyWithCompositeKeyTest.php b/tests/Tests/ORM/Functional/EagerFetchOneToManyWithCompositeKeyTest.php
index 82b9d0b8acb..4a3645f5e3e 100644
--- a/tests/Tests/ORM/Functional/EagerFetchOneToManyWithCompositeKeyTest.php
+++ b/tests/Tests/ORM/Functional/EagerFetchOneToManyWithCompositeKeyTest.php
@@ -6,6 +6,7 @@
use Doctrine\Tests\Models\EagerFetchedCompositeOneToMany\RootEntity;
use Doctrine\Tests\Models\EagerFetchedCompositeOneToMany\SecondLevel;
+use Doctrine\Tests\Models\EagerFetchedCompositeOneToMany\SecondLevelWithoutCompositePrimaryKey;
use Doctrine\Tests\OrmFunctionalTestCase;
final class EagerFetchOneToManyWithCompositeKeyTest extends OrmFunctionalTestCase
@@ -13,7 +14,7 @@ final class EagerFetchOneToManyWithCompositeKeyTest extends OrmFunctionalTestCas
/** @ticket 11154 */
public function testItDoesNotThrowAnExceptionWhenTriggeringALoad(): void
{
- $this->setUpEntitySchema([RootEntity::class, SecondLevel::class]);
+ $this->setUpEntitySchema([RootEntity::class, SecondLevel::class, SecondLevelWithoutCompositePrimaryKey::class]);
$a1 = new RootEntity(1, 'A');