DoctrineBundle Documentation

Symfony Bundle for Doctrine ORM and DBAL

4,830 stars PHP PHP 1 file · ~21,119 tokens #bundle#doctrine#symfony#symfony-bundle
RAW Doc

File: README.md

Doctrine Bundle

Doctrine DBAL & ORM Bundle for the Symfony Framework.


What is Doctrine?

The Doctrine Project is the home of a selected set of PHP libraries primarily focused on providing persistence
services and related functionality. Its prize projects are a Object Relational Mapper and the Database Abstraction
Layer it is built on top of. You can read more about the projects below or view a list of all projects.

Object relational mapper (ORM) for PHP that 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 Hibernates HQL. This provides developers with a powerful
alternative to SQL that maintains flexibility without requiring unnecessary code duplication.

DBAL is a powerful database abstraction layer with many features for database schema introspection,
schema management and PDO abstraction.

Documentation

The documentation is rendered on the symfony.com website.
The source of the documentation is available in the docs folder.


File: composer.json

{
"name": "doctrine/doctrine-bundle",
"description": "Symfony DoctrineBundle",
"license": "MIT",
"type": "symfony-bundle",
"keywords": [
"DBAL",
"ORM",
"Database",
"Persistence"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "[email protected]"
},
{
"name": "Benjamin Eberlei",
"email": "[email protected]"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
},
{
"name": "Doctrine Project",
"homepage": "https://www.doctrine-project.org/"
}
],
"homepage": "https://www.doctrine-project.org",
"require": {
"php": "^8.4",
"ext-mbstring": "",
"doctrine/dbal": "^4.0",
"doctrine/deprecations": "^1.0",
"doctrine/persistence": "^4",
"doctrine/sql-formatter": "^1.0.1",
"symfony/cache": "^6.4 || ^7.0 || ^8.0",
"symfony/config": "^6.4 || ^7.0 || ^8.0",
"symfony/console": "^6.4 || ^7.0 || ^8.0",
"symfony/dependency-injection": "^6.4 || ^7.0 || ^8.0",
"symfony/doctrine-bridge": "^6.4.3 || ^7.0.3 || ^8.0",
"symfony/framework-bundle": "^6.4 || ^7.0 || ^8.0",
"symfony/service-contracts": "^3"
},
"require-dev": {
"doctrine/coding-standard": "^14",
"doctrine/orm": "^3.4.4",
"phpstan/phpstan": "^2.1.13",
"phpstan/phpstan-phpunit": "2.0.3",
"phpstan/phpstan-strict-rules": "^2",
"phpstan/phpstan-symfony": "^2.0.9",
"phpunit/phpunit": "^12.3.10",
"psr/log": "^3.0",
"symfony/doctrine-messenger": "^6.4 || ^7.0 || ^8.0",
"symfony/expression-language": "^6.4 || ^7.0 || ^8.0",
"symfony/http-kernel": "^6.4 || ^7.0 || ^8.0",
"symfony/lock": "^6.4 || ^7.0 || ^8.0",
"symfony/messenger": "^6.4 || ^7.0 || ^8.0",
"symfony/property-info": "^6.4 || ^7.0 || ^8.0",
"symfony/runtime": "^6.4 || ^7.0 || ^8.0",
"symfony/security-bundle": "^6.4 || ^7.0 || ^8.0",
"symfony/stopwatch": "^6.4 || ^7.0 || ^8.0",
"symfony/string": "^6.4 || ^7.0 || ^8.0",
"symfony/twig-bridge": "^6.4 || ^7.0 || ^8.0",
"symfony/validator": "^6.4 || ^7.0 || ^8.0",
"symfony/web-profiler-bundle": "^6.4 || ^7.0 || ^8.0",
"symfony/yaml": "^6.4 || ^7.0 || ^8.0",
"twig/twig": "^3.21.1 || ^4"
},
"conflict": {
"doctrine/orm": "<3.0 || >=4.0",
"twig/twig": "<3.0.4 || >=5"
},
"suggest": {
"ext-pdo": "
",
"doctrine/orm": "The Doctrine ORM integration is optional in the bundle.",
"symfony/web-profiler-bundle": "To use the data collector."
},
"minimum-stability": "dev",
"autoload": {
"psr-4": {
"Doctrine\Bundle\DoctrineBundle\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Doctrine\Bundle\DoctrineBundle\Tests\": "tests",
"Fixtures\": "tests/DependencyInjection/Fixtures"
}
},
"config": {
"allow-plugins": {
"composer/package-versions-deprecated": true,
"dealerdirect/phpcodesniffer-composer-installer": true,
"symfony/flex": true,
"symfony/runtime": false
},
"sort-packages": true
},
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd"
}
}
}


File: SECURITY.md

Security

If you find a Security bug in Doctrine, please follow our
Security reporting guidelines.

Security vulnerabilities should be reported to [email protected]
and not posted on the GitHub issue tracker of the project.


File: UPGRADE-2.10.md

UPGRADE FROM 2.9 to 2.10

Configuration

Preparing for a new `report_fields_where_declared` mapping driver mode

Doctrine ORM 2.16+ makes a change to how the annotations and attribute mapping drivers report fields inherited from parent classes. For details, see https://github.com/doctrine/orm/pull/10455. It will trigger a deprecation notice unless the new mode is activated. In ORM 3.0, the new mode will be the only one.

The new mode does not should not make a difference for regular, valid use cases, but may lead to MappingExceptions for users with certain configurations that were not meant to be supported by the ORM in the first place. To avoid surprising users (even when their configuration is invalid) during a 2.16 minor version upgrade, the transition to this new mode was implemented as an opt-in. This way, you can try and deal with the change any time you see fit.

In version 2.10+ of this bundle, a new configuration setting report_fields_where_declared was added at the entity manager configuration level. Set it to true to switch the mapping driver for the corresponding entity manager to the new mode. It is only relevant for mapping configurations using attributes or annotations.

Unless you set it to true, Doctrine ORM will emit deprecation messages mentioning this new setting.

Preparing for the XSD validation for XML drivers

Doctrine ORM 2.14+ adds support for validating the XSD of XML mapping files. In ORM 3.0, this validation will be mandatory.

As the ecosystem is known to rely on custom elements in the XML mapping files that are forbidden when validating the XSD (for instance when using gedmo/doctrine-extensions), this validation is opt-in thanks to a validate_xml_mapping setting at the entity manager configuration level.

Unless you set it to true, Doctrine ORM will emit deprecation messages mentioning the XSD validation.

Deprecations

  • Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface has been deprecated. Use the #[AsDoctrineListener] attribute instead.

File: UPGRADE-2.12.md

UPGRADE FROM 2.11 to 2.12

Configuration

Controller resolver auto mapping default configuration will be changed

The default value of doctrine.orm.controller_resolver.auto_mapping will be changed from true to false in 3.0.

Auto mapping uses any route parameter that matches with a field name of the Entity to resolve as criteria in a find by query.

If you are relying on this functionality, you will need to configure it explicitly to silence the deprecation notice.


File: UPGRADE-2.13.md

UPGRADE FROM 2.12 to 2.13

Configuration

Controller resolver auto mapping deprecated

The controller resolver auto mapping functionality has been deprecated with Symfony 7.1, and is replaced with explicit mapped route parameters. Enabling the auto mapper by default using this bundle is now deprecated as well.

Auto mapping uses any route parameter that matches with a field name of the Entity to resolve as criteria in a find by query.

If you are relying on this functionality, you can update your code to use explicit mapped route parameters instead.


File: UPGRADE-2.17.md

UPGRADE FROM 2.16 to 2.17

DoctrineExtension

Minor breaking change:
Doctrine\Bundle\DoctrineBundle\DependencyInjection\DoctrineExtension no
longer extends
Symfony\Bridge\Doctrine\DependencyInjection\AbstractDoctrineExtension.

Configuration

The `doctrine.orm.entity_managers.some_em.report_fields_where_declared` configuration option is deprecated

This option is a no-op when using doctrine/orm 3 and has been conditionally
deprecated. You should stop using it as soon as you upgrade to Doctrine ORM 3.

The `doctrine.dbal.connections.some_connection.disable_type_comments` configuration option is deprecated

This option is a no-op when using doctrine/dbal 4 and has been conditionally
deprecated. You should stop using it as soon as you upgrade to Doctrine DBAL 4.

The `doctrine.dbal.connections.some_connection.use_savepoints` configuration option is deprecated

This option is a no-op when using doctrine/dbal 4 and has been conditionally
deprecated. You should stop using it as soon as you upgrade to Doctrine DBAL 4.

ConnectionFactory::createConnection() signature change

The signature of ConnectionFactory::createConnection() will change with
version 3.0 of the bundle.

As soon as you upgrade to Doctrine DBAL 4, you should use stop passing an event
manager argument.

diff
- $connectionFactory->createConnection($params, $config, $eventManager, $mappingTypes)
+ $connectionFactory->createConnection($params, $config, $mappingTypes)

As a small breaking change, it is no longer fully possible to use named
arguments with that method until 3.0.


File: UPGRADE-2.18.md

UPGRADE FROM 2.17 to 2.18

DoctrineOrmMappingsPass

The `DoctrineOrmMappingsPass::createYamlMappingDriver()` method is deprecated

This method is deprecated with no replacement planned and will be removed in
DoctrineBundle 3.0.

The `DoctrineOrmMappingsPass::createAnnotationMappingDriver()` method is deprecated

This method is deprecated with no replacement planned and will be removed in
DoctrineBundle 3.0.


File: UPGRADE-2.19.md

UPGRADE FROM 2.18 to 2.19

Configuration

BC Break: Native return type on Twig extension

A native return type array has been added to
Doctrine\Bundle\DoctrineBundle\Twig\DoctrineExtension. That class is not
meant to be extended, but if a downstream project did that, the return type
needs to be added there as well.

When using PHP 8.4 or higher in combination with Doctrine ORM 3.4 or
higher, the following configuration settings are deprecated:

  • auto_generate_proxy_classes
  • proxy_namespace
  • proxy_dir

Instead, they should be unset, and enable_native_lazy_objects should
be set to true.


File: UPGRADE-3.0.md

UPGRADE FROM 2.x to 3.0

Compatibility

Configuring caching options to use services backed by doctrine/cache is no
longer supported. Migrate to PSR-6 services instead.

The minimum required PHP version is now 8.4.

Support for the following major versions of the following packages has been dropped:

  • doctrine/dbal 3
  • doctrine/persistence 3
  • doctrine/orm 2
  • psr/log 1 and 2
  • twig/twig 2

More details below

Support for `doctrine/orm` 2 is dropped

This makes DisconnectedMetadataFactory redundant, as it relies on code
available only in doctrine/orm 2. It has been removed, as well as
ClassMetadataConnection.

Support for the YML and annotation metadata drivers has been dropped.

Doctrine\Bundle\DoctrineBundle\Repository\LazyServiceEntityRepository has
been removed without replacement.

Commands

All command classes in the Doctrine\Bundle\DoctrineBundle\Command\Proxy
namespace have been removed. Use the original commands provided by Doctrine
DBAL and ORM directly.

doctrine:query:sql has been removed. Use dbal:run-sql instead. All other
commands use the original command classes directly.

doctrine:mapping:convert and doctrine:ensure-production-settings have been
removed and do not have replacements.

Doctrine\Bundle\DoctrineBundle\Command\ImportMappingCommand has been removed
and does not have a replacement.

Configuration

no-op configuration options removed

The following configuration options are no-ops when using doctrine/orm 3 and
have been removed:

  • doctrine.orm.entity_managers.some_em.report_fields_where_declared
  • doctrine.orm.enable_lazy_ghost_objects

Also, the 3 following options were no-ops when enabling native lazy objects
and have been removed as well:

  • doctrine.orm.auto_generate_proxy_classes
  • doctrine.orm.proxy_dir
  • doctrine.orm.proxy_namespace

The `doctrine.dbal.default_table_options.collate` default table option is removed

Use doctrine.dbal.default_table_options.collation instead.

The `doctrine.dbal.override_url` option is removed

There is no replacement for this option.

The `doctrine.dbal.types.some_custom_type.commented` option is removed

The commented option for custom types is no longer supported and has been
removed.

The `doctrine.dbal.connection.some_connection.disable_type_comments` option is removed

The disable_type_comments option for connections is no longer supported and has
been removed.

The `doctrine.dbal.connection.some_connection.platform_service` option is removed

The platform_service option for connections is no longer supported and has
been removed.

The `doctrine.dbal.connection.some_connection.keep_slave` and `doctrine.dbal.connection.some_connection.slaves` option is removed

doctrine.dbal.connection.some_connection.slaves becomes
doctrine.dbal.connection.some_connection.replicas.

The `doctrine.dbal.connection.some_connection.use_savepoints` option is removed

The use_savepoints option for connections is no longer supported and
has been removed.

Controller resolver auto mapping can no longer be configured

The doctrine.orm.controller_resolver.auto_mapping option now only accepts false as value, to disallow the usage of the controller resolver auto mapping feature by default. The configuration option will be fully removed in 4.0.

Auto mapping used any route parameter that matches with a field name of the Entity to resolve as criteria in a find by query. This method has been deprecated in Symfony 7.1 and is replaced with mapped route parameters.

If you were relying on this functionality, you will need to update your code to use explicit mapped route parameters instead.

URL overrides are no longer allowed

When using the doctrine.dbal.url configuration option, you can no longer
specify other configuration options that would conflict with it, such as
dbname, host, etc.

Service class parameters removed

The following service class parameters have been removed:

  • doctrine.class
  • doctrine.data_collector.class
  • doctrine.dbal.configuration.class
  • doctrine.dbal.connection.event_manager.class
  • doctrine.dbal.connection_factory.class
  • doctrine.orm.configuration.class
  • doctrine.orm.entity_listener_resolver.class
  • doctrine.orm.entity_manager.class
  • doctrine.orm.listeners.attach_entity_listeners.class
  • doctrine.orm.listeners.resolve_target_entity.class
  • doctrine.orm.manager_configurator.class
  • doctrine.orm.metadata.attribute.class
  • doctrine.orm.metadata.driver_chain.class
  • doctrine.orm.metadata.php.class
  • doctrine.orm.metadata.staticphp.class
  • doctrine.orm.metadata.xml.class
  • doctrine.orm.naming_strategy.default.class
  • doctrine.orm.naming_strategy.underscore.class
  • doctrine.orm.quote_strategy.ansi.class
  • doctrine.orm.quote_strategy.default.class
  • doctrine.orm.second_level_cache.cache_configuration.class
  • doctrine.orm.second_level_cache.default_cache_factory.class
  • doctrine.orm.second_level_cache.default_region.class
  • doctrine.orm.second_level_cache.filelock_region.class
  • doctrine.orm.second_level_cache.logger_chain.class
  • doctrine.orm.second_level_cache.logger_statistics.class
  • doctrine.orm.second_level_cache.regions_configuration.class
  • doctrine.orm.security.user.provider.class
  • doctrine.orm.typed_field_mapper.default.class
  • doctrine.orm.validator.unique.class
  • doctrine.orm.validator_initializer.class
  • form.type_guesser.doctrine.class

If your application was relying on these parameters, you should update your
service definitions to use the class names directly instead of parameter
references.

ConnectionFactory::createConnection() signature change

The signature of ConnectionFactory::createConnection() changed.
You should use stop passing an event manager argument.

diff
- $connectionFactory->createConnection($params, $config, $eventManager, $mappingTypes)
+ $connectionFactory->createConnection($params, $config, $mappingTypes)

DependencyInjection namespace becomes internal

The Doctrine\Bundle\DoctrineBundle\DependencyInjection namespace is now
considered internal, and all classes inside it are marked as final, except for
Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineORMMappingsPass.
Don't reference any classes from this namespace directly, except the one
mentioned earlier.

`Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventListenerInterface` has been removed

Use the #[Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener]
attribute instead.

`Doctrine\Bundle\DoctrineBundle\Dbal\BlacklistSchemaAssetsFilter` has been removed

Implement your own include/exclude mechanism instead.

Type declarations

Native type declarations have been added to all constants, properties, and
methods.

Twig filters

The Twig filter doctrine_pretty_query has been removed.


File: UPGRADE-3.1.md

UPGRADE FROM 3.0 to 3.1

Configuration

The doctrine.orm.controller_resolver.auto_mapping only accepts false
as value since 3.0 and supplying the value explicitly is now marked as
deprecated.

The doctrine.orm.entity_managers.some_em.enable_native_lazy_objects
configuration option is deprecated and will be removed in DoctrineBundle 4.0,
as native lazy objects are now always enabled.


File: UPGRADE-3.2.md

UPGRADE FROM 3.1 to 3.2

DoctrineOrmMappingsPass

The $aliasMap argument of the DoctrineOrmMappingsPass class and methods
is removed. Namespace aliases are no longer supported in Doctrine.


File: .doctrine-project.json

{
"active": true,
"name": "Doctrine Bundle",
"shortName": "DoctrineBundle",
"slug": "doctrine-bundle",
"versions": [
{
"name": "4.0",
"branchName": "4.0.x",
"slug": "latest",
"upcoming": true
},
{
"name": "3.4",
"branchName": "3.4.x",
"slug": "3.4",
"upcoming": true
},
{
"name": "3.3",
"branchName": "3.3.x",
"slug": "3.3",
"current": true
},
{
"name": "3.2",
"slug": "3.2",
"maintained": false
},
{
"name": "3.1",
"slug": "3.1",
"maintained": false
},
{
"name": "3.0",
"slug": "3.0",
"maintained": false
},
{
"name": "2.19",
"branchName": "2.19.x",
"slug": "2.19",
"maintained": true
},
{
"name": "2.18",
"slug": "2.18",
"maintained": false
},
{
"name": "2.16",
"slug": "2.16",
"maintained": false
},
{
"name": "2.15",
"slug": "2.15",
"maintained": false
},
{
"name": "2.14",
"slug": "2.14",
"maintained": false
},
{
"name": "2.13",
"slug": "2.13",
"maintained": false
},
{
"name": "2.12",
"slug": "2.12",
"maintained": false
},
{
"name": "2.11",
"slug": "2.11",
"maintained": false
},
{
"name": "2.10",
"slug": "2.10",
"maintained": false
},
{
"name": "2.7",
"slug": "2.7",
"maintained": false
},
{
"name": "2.6",
"slug": "2.6",
"maintained": false
},
{
"name": "2.0",
"slug": "2.0",
"maintained": false
},
{
"name": "1.12",
"slug": "1.12",
"maintained": false
}
]
}


File: .symfony.bundle.yaml

branches:
- "2.6.x"
- "2.7.x"
- "2.10.x"
- "2.11.x"
- "2.12.x"
- "2.13.x"
- "2.14.x"
- "2.15.x"
- "2.16.x"
- "2.18.x"
- "2.19.x"
- "3.0.x"
- "3.1.x"
- "3.2.x"
- "3.3.x"
- "4.0.x"
maintained_branches:
- "2.18.x"
- "2.19.x"
- "3.2.x"
- "3.3.x"
- "4.0.x"
doc_dir: "docs/en/"
current_branch: "3.2.x"
dev_branch: "3.3.x"


File: docs/composer.json

{
"require-dev": {
"doctrine/docs-builder": "^1.0"
},
"config": {
"sort-packages": true
}
}


File: docs/en/custom-id-generators.rst

Custom ID Generators

Custom ID generators are classes that allow implementing custom logic to generate
identifiers for your entities. They extend Doctrine\ORM\Id\AbstractIdGenerator
and implement the custom logic in the generate(EntityManager $em, $entity)
method. Before Doctrine bundle 2.3, custom ID generators were always created
without any constructor arguments.

Starting with Doctrine bundle 2.3, the CustomIdGenerator attribute can be
used to reference any services tagged with the doctrine.id_generator tag.
If you enable autoconfiguration (which is the default most of the time), Symfony
will add this tag for you automatically if you implement your own id-generators.

When using Symfony's Doctrine bridge and Uid component 5.3 or higher, two services
are provided: doctrine.ulid_generator to generate ULIDs, and
doctrine.uuid_generator to generate UUIDs.

.. code-block:: php

text
<?php
// User.php

use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class User
{
    #[ORM\Id]
    #[ORM\Column(type: 'uuid')]
    #[ORM\GeneratedValue(strategy: 'CUSTOM')]
    #[ORM\CustomIdGenerator('doctrine.uuid_generator')]
    private $id;

    // ....
}

See also
https://www.doctrine-project.org/projects/doctrine-orm/en/3.3/reference/attributes-reference.html#attrref_customidgenerator
for more info about custom ID generators.


File: docs/en/dbal-type.rst

DBAL Types

Custom DBAL types can be registered using the AsDbalType attribute. This
attribute allows you to define a name for your custom type directly in the class
definition. If the name is not provided, the class name will be used as the default.

To register a custom DBAL type, create a class that extends
Doctrine\DBAL\Types\Type and add the #[AsDbalType] attribute to it:

.. code-block:: php

text
namespace App\Doctrine\Type;

use Doctrine\Bundle\DoctrineBundle\Attribute\AsDbalType;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type;

#[AsDbalType(name: 'money')]
class MoneyType extends Type
{
    public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
    {
        return $platform->getDecimalTypeDeclarationSQL($column);
    }

    public function convertToPHPValue(mixed $value, AbstractPlatform $platform): mixed
    {
        return $value;
    }

    public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): mixed
    {
        return $value;
    }
}

When using the AsDbalType attribute, the type will be automatically
registered with Doctrine.

Manual Registration

Alternatively, you can register custom types in your configuration:

.. configuration-block::

text
.. code-block:: yaml

    # config/packages/doctrine.yaml
    doctrine:
        dbal:
            types:
                money: App\Doctrine\Type\MoneyType

.. code-block:: xml

    
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:doctrine="http://symfony.com/schema/dic/doctrine"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/doctrine
            http://symfony.com/schema/dic/doctrine/doctrine-1.0.xsd">

        <doctrine:config>
            <doctrine:dbal>
                <doctrine:type name="money">App\Doctrine\Type\MoneyType</doctrine:type>
            </doctrine:dbal>
        </doctrine:config>
    </container>

.. code-block:: php

    // config/packages/doctrine.php
    use App\Doctrine\Type\MoneyType;
    use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

    return static function (ContainerConfigurator $containerConfigurator): void {
        $containerConfigurator->extension('doctrine', [
            'dbal' => [
                'types' => [
                    'money' => MoneyType::class,
                ],
            ],
        ]);
    };

File: docs/en/doctrine-console.rst

Doctrine Console

Some Doctrine packages such as doctrine/dbal and doctrine/orm
provide useful console commands to interact with your database and your
entities:

  • Doctrine DBAL Commands <https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/cli-tools.html#cli-tools>_
  • Doctrine ORM Commands <https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/tools.html#doctrine-console>_

This bundle automatically registers those commands, but it renames them
in the process so as to group them under the doctrine: namespace.

Note that the bundle also provide some additional commands that are not
part of the aforementioned packages.

Command Name Mapping

The following table shows the mapping between the original Doctrine command
names and the names used by this bundle:

+--------------------------------------------+---------------------------------------+
| Bundle Command Name | Original Doctrine Command Name |
+============================================+=======================================+
| doctrine:cache:clear-metadata | orm:clear-cache:metadata |
+--------------------------------------------+---------------------------------------+
| doctrine:cache:clear-query | orm:clear-cache:query |
+--------------------------------------------+---------------------------------------+
| doctrine:cache:clear-result | orm:clear-cache:result |
+--------------------------------------------+---------------------------------------+
| doctrine:cache:clear-collection-region | orm:clear-cache:region:collection |
+--------------------------------------------+---------------------------------------+
| doctrine:cache:clear-entity-region | orm:clear-cache:region:entity |
+--------------------------------------------+---------------------------------------+
| doctrine:cache:clear-query-region | orm:clear-cache:region:query |
+--------------------------------------------+---------------------------------------+
| doctrine:schema:create | orm:schema-tool:create |
+--------------------------------------------+---------------------------------------+
| doctrine:schema:drop | orm:schema-tool:drop |
+--------------------------------------------+---------------------------------------+
| doctrine:schema:update | orm:schema-tool:update |
+--------------------------------------------+---------------------------------------+
| doctrine:mapping:info | orm:info |
+--------------------------------------------+---------------------------------------+
| doctrine:mapping:describe | orm:mapping:describe |
+--------------------------------------------+---------------------------------------+
| doctrine:query:dql | orm:run-dql |
+--------------------------------------------+---------------------------------------+
| doctrine:schema:validate | orm:validate-schema |
+--------------------------------------------+---------------------------------------+

Additionally, the bundle provides the following commands:

  • doctrine:database:create
  • doctrine:database:drop

To get a list of all available Doctrine commands, run:

.. code-block:: console

text
php bin/console list doctrine

It is possible to get help on any specific command. For example,
to get help on the doctrine:schema:update command, run:

.. code-block:: console

text
php bin/console doctrine:schema:update --help

File: docs/en/entity-listeners.rst

Entity Listeners

Entity listeners that are services must be registered with the entity listener
resolver. On top of the attribute in the entity class, you have to tag the
service with doctrine.orm.entity_listener for it to be automatically added
to the resolver. Use the (optional) entity_manager attribute to specify
which entity manager it should be registered with.

Full example:

.. code-block:: php

text
<?php
// User.php

use Doctrine\ORM\Mapping as ORM;
use App\UserListener;

#[ORM\Entity]
#[ORM\EntityListeners([UserListener::class])]
class User
{
    // ....
}

.. configuration-block::

text
.. code-block:: yaml

    services:
        App\UserListener:
            tags:
                # Minimal configuration below
                - { name: doctrine.orm.entity_listener }
                # Or, optionally, you can give the entity manager name as below
                #- { name: doctrine.orm.entity_listener, entity_manager: custom }

.. code-block:: php

    // config/services.php
    namespace Symfony\Component\DependencyInjection\Loader\Configurator;

    use App\UserListener;

    return static function (ContainerConfigurator $configurator) {
        $services = $configurator->services();

        // Minimal configuration below
        $services->set(UserListener::class)
            ->tag('doctrine.orm.entity_listener')
        ;

        // Or, optionally, you can give the entity manager name as below
        // $services->set(UserListener::class)
        //     ->tag('doctrine.orm.entity_listener', ['entity_manager' => 'custom'])
        // ;
    };

Starting with doctrine/orm 2.5 and Doctrine bundle 1.5.2, instead of registering
the entity listener on the entity, you can declare all options from the service
definition:

.. configuration-block::

text
.. code-block:: yaml

    services:
        App\UserListener:
            tags:
                -
                    name: doctrine.orm.entity_listener
                    event: preUpdate
                    entity: App\Entity\User
                    # entity_manager attribute is optional
                    entity_manager: custom
                    # method attribute is optional
                    method: validateEmail

.. code-block:: php

    // config/services.php
    namespace Symfony\Component\DependencyInjection\Loader\Configurator;

    use App\UserListener;

    return static function (ContainerConfigurator $configurator) {
        $services = $configurator->services();

        $services->set(UserListener::class)
            ->tag('doctrine.orm.entity_listener', [
                'event' => 'preUpdate',
                'entity' => 'App\Entity\User',
                // entity_manager attribute is optional
                'entity_manager' => 'custom',
                // method attribute is optional
                'method' => 'validateEmail',
            ])
        ;
    };

The event attribute is required if the entity listener is not registered on
the entity. If you don't specify the method attribute, it falls back on the
subscribed event name.

Starting with Doctrine bundle 1.12, if this method does not exist but if your entity listener is invokable, it falls
back on the __invoke() method.

See also
https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#entity-listeners
for more info on entity listeners and the resolver required by Symfony.


File: docs/en/event-listeners.rst

Event Listeners

In opposite to :doc:Entity Listeners </entity-listeners>, Event listeners
are services that listen for all entities in your application.

See https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#implementing-event-listeners
for more info on event listeners.

To register a service to act as an event listener you have to tag it with the
doctrine.event_listener tag:

Starting with Doctrine bundle 2.8, you can use the AsDoctrineListener
attribute to tag the service.

.. configuration-block::

text
.. code-block:: php-attributes

    // src/App/EventListener/SearchIndexer.php
    namespace App\EventListener;

    use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
    use Doctrine\ORM\Event\LifecycleEventArgs;

    #[AsDoctrineListener('postPersist'/*, 500, 'default'*/)]
    class SearchIndexer
    {
        public function postPersist(LifecycleEventArgs $event): void
        {
            // ...
        }
    }

.. code-block:: yaml

    # config/services.yaml
    services:
        # ...

        App\EventListener\SearchIndexer:
            tags:
                -
                    name: 'doctrine.event_listener'
                    # this is the only required option for the lifecycle listener tag
                    event: 'postPersist'

                    # listeners can define their priority in case multiple subscribers or listeners are associated
                    # to the same event (default priority = 0; higher numbers = listener is run earlier)
                    priority: 500

                    # you can also restrict listeners to a specific Doctrine connection
                    connection: 'default'

.. code-block:: php

    // config/services.php
    namespace Symfony\Component\DependencyInjection\Loader\Configurator;

    use App\EventListener\SearchIndexer;

    return static function (ContainerConfigurator $configurator) {
        $services = $configurator->services();

        // listeners are applied by default to all Doctrine connections
        $services->set(SearchIndexer::class)
            ->tag('doctrine.event_listener', [
                // this is the only required option for the lifecycle listener tag
                'event' => 'postPersist',

                // listeners can define their priority in case multiple subscribers or listeners are associated
                // to the same event (default priority = 0; higher numbers = listener is run earlier)
                'priority' => 500,

                // you can also restrict listeners to a specific Doctrine connection
                'connection' => 'default',
            ])
        ;
    };

File: docs/en/index.rst

DoctrineBundle

Integrates Doctrine's ORM and DBAL projects into Symfony applications. It provides
configuration options, console commands and even a web debug toolbar collector.

.. toctree::

text
installation
doctrine-console
dbal-type
entity-listeners
event-listeners
custom-id-generators
middlewares
configuration

File: docs/en/installation.rst

Installation

Step 1: Download the Bundle

Open a command console, enter your project directory and execute the following
command to download the latest stable version of this bundle:

.. code-block:: bash

text
$ composer require doctrine/doctrine-bundle

This command requires you to have Composer installed globally, as explained
in the installation chapter_ of the Composer documentation.

Step 2: Enable the Bundle

Your bundle should be automatically enabled by Flex.
In case you don't use Flex, you'll need to manually enable the bundle by
adding the following line in the config/bundles.php file of your project::

text
<?php
// config/bundles.php

return [
    // ...
    Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
    // ...
];

If you don't have a config/bundles.php file in your project, chances are that
you're using an older Symfony version. In this case, you should have an
app/AppKernel.php file instead. Edit such file::

text
<?php
// app/AppKernel.php

// ...
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = [
            // ...

            new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
        ];

        // ...
    }

    // ...
}

.. _installation chapter: https://getcomposer.org/doc/00-intro.md


File: docs/en/middlewares.rst

Middlewares

Doctrine DBAL supports middlewares. According to the DBAL documentation_:

text
"A middleware sits in the middle between the wrapper components and the driver"

They allow to decorate the following DBAL classes:

  • Doctrine\DBAL\Driver
  • Doctrine\DBAL\Driver\Connection
  • Doctrine\DBAL\Driver\Statement
  • Doctrine\DBAL\Driver\Result

Symfony, for instance, uses a middleware to harvest the queries executed
by the current page and make them available in the profiler.

.. _DBAL documentation: https://www.doctrine-project.org/projects/doctrine-dbal/en/current/reference/architecture.html#middlewares

You can also create your own middleware. This is an example of a (very)
simple middleware that prevents database connections with the root user.
The first step is to create the middleware:

.. code-block:: php

text
<?php

namespace App\Middleware;

use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\Middleware;

class PreventRootConnectionMiddleware implements Middleware
{
    public function wrap(Driver $driver): Driver
    {
        return new PreventRootConnectionDriver($driver);
    }
}

As you can see in the wrap method, the principle of a middleware is
to decorate Doctrine objects with your own objects bearing the logic you
need. Now, the connect method of the driver must be decorated in
PreventRootConnectionDriver to prevent connections with the root user:

.. code-block:: php

text
<?php

namespace App\Middleware;

use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware;
use SensitiveParameter;

final class PreventRootConnectionDriver extends AbstractDriverMiddleware
{
    public function connect(array $params): Connection
    {
        if (isset($params['user']) && $params['user'] === 'root') {
            throw new \LogicException('Connecting to the database with the root user is not allowed.');
        }

        return parent::connect($params);
    }
}

That's all! Connection with the root user is not possible anymore. Note
that connect is not the only method you can decorate in a Connection.
But thanks to the AbstractDriverMiddleware default implementation,
you only need to decorate the methods for which you want to add some logic.
Too see a more advanced example with a decoration of the Statement class,
you can look at the middleware implementation starting in the class
Symfony\Bridge\Doctrine\Middleware\Debug\Middleware of the
Doctrine Bridge. Decorating the Result class follows the same principle.

The middleware we've just created applies by default to all the connections.
If your application has several dbal connections, you can limit the middleware
scope to a subset of connections thanks to the AsMiddleware PHP attribute.
Let's limit our middleware to a connection named legacy:

.. code-block:: php

text
<?php

namespace App\Middleware;

use Doctrine\Bundle\DoctrineBundle\Attribute\AsMiddleware;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\Middleware;

#[AsMiddleware(connections: ['legacy'])]
class PreventRootConnectionMiddleware implements Middleware
{
    public function wrap(Driver $driver): Driver
    {
        return new PreventRootConnectionDriver($driver);
    }
}

If you register multiple middlewares in your application, they will be executed
in the order they were registered. If some middleware needs to be executed
before another, you can set priority through the AsMiddleware PHP attribute.
This priority can be any integer, positive or negative. The higher the priority,
the earlier the middleware is executed. If no priority is defined, the priority
is considered 0. Let's make sure our middleware is the first middleware
executed, so that we don't set up debugging or logging if the connection will
be prevented:

.. code-block:: php

text
<?php

namespace App\Middleware;

use Doctrine\Bundle\DoctrineBundle\Attribute\AsMiddleware;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\Middleware;

#[AsMiddleware(priority: 10)]
class PreventRootConnectionMiddleware implements Middleware
{
    public function wrap(Driver $driver): Driver
    {
        return new PreventRootConnectionDriver($driver);
    }
}

priority and connections can be used together to restrict a middleware
to a specific connection while changing its priority.

All the examples presented above assume autoconfigure is enabled.
If autoconfigure is disabled, the doctrine.middleware tag must be
added to the middleware. This tag supports a connections attribute to
limit the scope of the middleware and a priority attribute to change
the execution order of the registered middlewares.

.. note::

text
Middlewares have been introduced in version 3.2 of ``doctrine/dbal``
and at least the 2.6 version of ``doctrine/doctrine-bundle`` is needed
to integrate them in Symfony as shown above.

File: tests/DependencyInjection/Fixtures/config/yml/dbal_auto_commit.yml

doctrine:
dbal:
auto_commit: false


File: tests/DependencyInjection/Fixtures/config/yml/dbal_collect_schema_errors_disable.yml

doctrine:
dbal:
default_connection: mysql
connections:
profile_without_schema_validator:
logging: false
profiling: true
profiling_collect_schema_errors: false


File: tests/DependencyInjection/Fixtures/config/yml/dbal_collect_schema_errors_disable_no_profiling.yml

doctrine:
dbal:
default_connection: mysql
connections:
profile_without_schema_validator_no_profiling:
logging: false
profiling: false
profiling_collect_schema_errors: false


File: tests/DependencyInjection/Fixtures/config/yml/dbal_collect_schema_errors_enable.yml

doctrine:
dbal:
default_connection: mysql
connections:
profile_with_schema_validator:
logging: false
profiling: true
profiling_collect_schema_errors: true


File: tests/DependencyInjection/Fixtures/config/yml/dbal_dbname_suffix.yml

doctrine:
dbal:
url: 'mysql://root:password@database:3306/main?serverVersion=mariadb-12.1.1'
dbname_suffix: _test


File: tests/DependencyInjection/Fixtures/config/yml/dbal_driver_schemes.yml

doctrine:
dbal:
url: 'mysql://root:password@database:3306/main?serverVersion=mariadb-12.1.1'
driver_schemes:
postgresql: pgsql
my-scheme: my_driver


File: tests/DependencyInjection/Fixtures/config/yml/dbal_logging.yml

doctrine:
dbal:
default_connection: mysql
connections:
log:
logging: true
profiling: false
profile:
logging: false
profiling: true
profile_with_backtrace:
logging: false
profiling: true
profiling_collect_backtrace: true
backtrace_without_profile:
logging: false
profiling: false
profiling_collect_backtrace: true
both:
logging: true
profiling: true
profile_without_schema_validator:
logging: false
profiling: true
profiling_collect_schema_errors: true


File: tests/DependencyInjection/Fixtures/config/yml/dbal_oracle_connectstring.yml

doctrine:
dbal:
connectstring: scott@sales-server:1521/sales.us.example.com


File: tests/DependencyInjection/Fixtures/config/yml/dbal_oracle_instancename.yml

doctrine:
dbal:
instancename: mySuperInstance


File: tests/DependencyInjection/Fixtures/config/yml/dbal_result_cache.yml

doctrine:
dbal:
default_connection: connection_with_cache
connections:
connection_with_cache:
result_cache: example.cache
connection_without_cache: ~


File: tests/DependencyInjection/Fixtures/config/yml/dbal_schema_filter.yml

doctrine:
dbal:
default_connection: connection1
connections:
connection1:
schema_filter: ^(?!t_)
server_version: 9.4.0
connection2:
server_version: 9.4.0
connection3:
server_version: 9.4.0


File: tests/DependencyInjection/Fixtures/config/yml/dbal_schema_manager_factory.yml

doctrine:
dbal:
default_connection: custom_schema_manager_factory
connections:
default_schema_manager_factory: ~
custom_schema_manager_factory:
schema_manager_factory: custom_factory


File: tests/DependencyInjection/Fixtures/config/yml/dbal_service_multiple_connections.yml

doctrine:
dbal:
default_connection: mysql
connections:
mysql:
dbname: mysql_db
user: mysql_user
password: mysql_s3cr3t
unix_socket: /path/to/mysqld.sock
sqlite:
driver: pdo_sqlite
dbname: sqlite_db
user: sqlite_user
password: sqlite_s3cr3t
path: /tmp/db.sqlite
memory: true
options:
userDefinedFunctions:
asin:
callback: 'asin'
numArgs: 1
arbitraryValue: foo
oci:
driver: oci8
dbname: oracle_db
user: oracle_user
password: oracle_s3cr3t
servicename: oracle_service
service: true
pooled: true
charset: utf8
ibmdb2:
driver: ibm_db2
dbname: ibmdb2_db
user: ibmdb2_user
password: ibmdb2_s3cr3t
protocol: TCPIP
pgsql:
driver: pdo_pgsql
dbname: pgsql_schema
user: pgsql_user
password: pgsql_s3cr3t
default_dbname: pgsql_db
sslmode: require
sslrootcert: postgresql-ca.pem
sslcert: postgresql-cert.pem
sslkey: postgresql-key.pem
sslcrl: postgresql.crl
charset: utf8
sqlanywhere:
driver: sqlanywhere
host: localhost
port: 2683
server: sqlanywhere_server
dbname: sqlanywhere_db
user: sqlanywhere_user
password: sqlanywhere_s3cr3t
persistent: true
charset: utf8


File: tests/DependencyInjection/Fixtures/config/yml/dbal_service_single_connection.yml

doctrine:
dbal:
dbname: mysql_db
user: mysql_user
password: mysql_s3cr3t
unix_socket: /path/to/mysqld.sock
server_version: 9.4.0


File: tests/DependencyInjection/Fixtures/config/yml/dbal_service_single_primary_replica_connection.yml

doctrine:
dbal:
dbname: mysql_db
user: mysql_user
password: mysql_s3cr3t
unix_socket: /path/to/mysqld.sock
keep_replica: true
default_table_options:
engine: InnoDB
options:
!php/const PDO::ATTR_STRINGIFY_FETCHES: 1
replicas:
replica1:
user: replica_user
dbname: replica_db
password: replica_s3cr3t
unix_socket: /path/to/mysqld_replica.sock


File: tests/DependencyInjection/Fixtures/config/yml/dbal_types.yml

doctrine:
dbal:
default_connection: default
types:
test: Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\TestType
connections:
default: ~


File: tests/DependencyInjection/Fixtures/config/yml/orm_attach_entity_listener.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    entity_managers:
        default:
            entity_listeners:
                    ExternalBundles\Entities\FooEntity:
                        MyBundles\Listeners\FooEntityListener:
                            prePersist:
                            postPersist: [postPersist]
                            postLoad: [postLoadHandler]
                    ExternalBundles\Entities\BarEntity:
                            MyBundles\Listeners\BarEntityListener:
                                prePersist: [prePersist, prePersistHandler]
                            MyBundles\Listeners\LogDeleteEntityListener:
                                postDelete: [postDelete]

File: tests/DependencyInjection/Fixtures/config/yml/orm_attach_entity_listener_tag.yml

services:
entity_listener1:
class: EntityListener1
tags:
- { name: doctrine.orm.entity_listener, entity: My/Entity1, event: postLoad }

text
entity_listener2:
    class: EntityListener2
    tags:
        - { name: doctrine.orm.entity_listener, entity_manager: em2, entity: My/Entity2, event: preFlush, method: preFlushHandler }

invokable_entity_listener:
    class: Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\Fixtures\InvokableEntityListener
    tags:
        - { name: doctrine.orm.entity_listener, entity: My/Entity1, event: loadClassMetadata }
        - { name: doctrine.orm.entity_listener, entity: My/Entity1, event: postPersist }

grand_parent_entity_listener:
    class: GrandParentEntityListener

parent_entity_listener:
    parent: grand_parent_entity_listener
    class: ParentEntityListener

children_entity_listener:
    parent: parent_entity_listener
    tags:
        - { name: doctrine.orm.entity_listener, entity: My/Entity3, event: postLoad, priority: 1 }

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    default_entity_manager: em1
    entity_managers:
        em1:
        em2:

File: tests/DependencyInjection/Fixtures/config/yml/orm_attach_entity_listeners_two_connections.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db
foobar:
dbname: foobar

text
orm:
    default_entity_manager: em1
    entity_managers:
        em1:
            connection: default
        em2:
            connection: foobar

File: tests/DependencyInjection/Fixtures/config/yml/orm_attach_lazy_entity_listener.yml

services:
custom_entity_listener_resolver:
class: Doctrine\Bundle\DoctrineBundle\Mapping\ContainerEntityListenerResolver
arguments:
- '@service_container'

text
entity_listener1:
    class: EntityListener1
    tags:
        - { name: doctrine.orm.entity_listener, lazy: true }

entity_listener2:
    class: EntityListener2
    tags:
        - { name: doctrine.orm.entity_listener, entity_manager: em2, lazy: true }

entity_listener3:
    class: EntityListener3
    tags:
        - { name: doctrine.orm.entity_listener, lazy: false }

entity_listener4:
    class: EntityListener4
    tags:
        - { name: doctrine.orm.entity_listener }

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    default_entity_manager: em1
    entity_managers:
        em1:
        em2:
          entity_listener_resolver: custom_entity_listener_resolver

File: tests/DependencyInjection/Fixtures/config/yml/orm_caches.yml

services:
cache.psr6:
class: Symfony\Component\Cache\Adapter\ArrayAdapter

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db
server_version: 9.4.0

text
orm:
    default_entity_manager: metadata_cache_none
    entity_managers:
        metadata_cache_none: ~
        metadata_cache_pool:
            metadata_cache_driver:
                type: pool
                pool: cache.psr6
        metadata_cache_service_psr6:
            metadata_cache_driver:
                type: service
                id: cache.psr6

        query_cache_pool:
            query_cache_driver:
                type: pool
                pool: cache.psr6
        query_cache_service_psr6:
            query_cache_driver:
                type: service
                id: cache.psr6

        result_cache_pool:
            result_cache_driver:
                type: pool
                pool: cache.psr6
        result_cache_service_psr6:
            result_cache_driver:
                type: service
                id: cache.psr6

        second_level_cache_pool:
            second_level_cache:
                enabled: true
                region_cache_driver:
                    type: pool
                    pool: cache.psr6
        second_level_cache_service_psr6:
            second_level_cache:
                enabled: true
                region_cache_driver:
                    type: service
                    id: cache.psr6

File: tests/DependencyInjection/Fixtures/config/yml/orm_entity_listener_abstract.yml

services:
entity_listener:
abstract: true
class: EntityListener
tags:
- { name: doctrine.orm.entity_listener }

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    default_entity_manager: em1
    entity_managers:
        em1:

File: tests/DependencyInjection/Fixtures/config/yml/orm_entity_listener_custom_resolver.yml

services:
custom_entity_listener_resolver:
class: Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\Fixtures\CustomEntityListenerServiceResolver
public: false

text
entity_listener:
    class: EntityListener
    public: false
    tags:
        - { name: doctrine.orm.entity_listener }

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    default_entity_manager: em1
    entity_managers:
        em1:
            entity_listener_resolver: custom_entity_listener_resolver

File: tests/DependencyInjection/Fixtures/config/yml/orm_entity_listener_lazy_private.yml

services:
entity_listener:
public: false
class: EntityListener
tags:
- { name: doctrine.orm.entity_listener, lazy: true }

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    default_entity_manager: em1
    entity_managers:
        em1:

File: tests/DependencyInjection/Fixtures/config/yml/orm_entity_listener_lazy_resolver_without_interface.yml

services:
custom_resolver:
class: Doctrine\ORM\Mapping\DefaultEntityListenerResolver

text
entity_listener:
    class: EntityListener
    tags:
        - { name: doctrine.orm.entity_listener, lazy: true }

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    default_entity_manager: em1
    entity_managers:
        em1:
            entity_listener_resolver: custom_resolver

File: tests/DependencyInjection/Fixtures/config/yml/orm_entity_listener_resolver.yml

services:
entity_listener_resolver:
class: Doctrine\ORM\Mapping\DefaultEntityListenerResolver

text
entity_listener1:
    class: EntityListener
    tags:
        - { name: doctrine.orm.entity_listener }

entity_listener2:
    class: EntityListener
    tags:
        - { name: doctrine.orm.entity_listener, entity_manager: em2 }

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    default_entity_manager: em1
    entity_managers:
        em1:
        em2:
            entity_listener_resolver: entity_listener_resolver

File: tests/DependencyInjection/Fixtures/config/yml/orm_fetch_mode_subselect_batch_size.yml

doctrine:
dbal:
default_connection: default

text
orm:
    fetch_mode_subselect_batch_size: 10000

File: tests/DependencyInjection/Fixtures/config/yml/orm_filters.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db
server_version: 9.4.0

text
orm:
    filters:
        soft_delete:
            class: Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\TestFilter
            enabled: true
        myFilter:
            class: Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\TestFilter
            enabled: true
            parameters:
                myParameter: myValue
                mySecondParameter: mySecondValue

File: tests/DependencyInjection/Fixtures/config/yml/orm_functions.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    entity_managers:
        default:
            mappings:
                XmlBundle: ~
            dql:
                string_functions:
                    test_string: Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\TestStringFunction
                numeric_functions:
                    test_numeric: Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\TestNumericFunction
                datetime_functions:
                    test_datetime: Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\TestDatetimeFunction

File: tests/DependencyInjection/Fixtures/config/yml/orm_hydration_mode.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    entity_managers:
        default:
            hydrators:
                test_hydrator: Symfony\Bundle\DoctrineBundle\Tests\DependencyInjection\TestHydrator
            mappings:
                XmlBundle: ~

File: tests/DependencyInjection/Fixtures/config/yml/orm_identity_generation_preferences.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    default_entity_manager: em1
    entity_managers:
        em1:
            mappings:
                XmlBundle: ~
            identity_generation_preferences:
                Doctrine\DBAL\Platforms\PostgreSQLPlatform: identity
        em2:
            mappings:
                XmlBundle: ~
            identity_generation_preferences:
                Doctrine\DBAL\Platforms\PostgreSQLPlatform: sequence

File: tests/DependencyInjection/Fixtures/config/yml/orm_multiple_em_bundle_mappings.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    default_entity_manager: em2
    entity_managers:
        em1:
            mappings:
                AttributesBundle:
                  type: attribute
        em2:
            validate_xml_mapping: true
            mappings:
                XmlBundle:
                    dir: Resources/config/doctrine
                    alias: xml
                manual:
                    type: xml
                    prefix: Fixtures\Bundles\XmlBundle
                    dir: "%kernel.root_dir%/tests/DependencyInjection/Fixtures/Bundles/XmlBundle/Resources/config/doctrine"
                    alias: TestAlias

File: tests/DependencyInjection/Fixtures/config/yml/orm_namingstrategy.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    default_entity_manager: em1
    entity_managers:
        em1:
            mappings:
                XmlBundle: ~
            naming_strategy: doctrine.orm.naming_strategy.default
        em2:
            mappings:
                XmlBundle: ~
            naming_strategy: doctrine.orm.naming_strategy.underscore

File: tests/DependencyInjection/Fixtures/config/yml/orm_native_lazy_objects_default.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db
server_version: 9.4.0

text
orm: ~

File: tests/DependencyInjection/Fixtures/config/yml/orm_native_lazy_objects_disable.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db
server_version: 9.4.0

text
orm:
    enable_native_lazy_objects: false

File: tests/DependencyInjection/Fixtures/config/yml/orm_native_lazy_objects_enable.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db
server_version: 9.4.0

text
orm:
    enable_native_lazy_objects: true

File: tests/DependencyInjection/Fixtures/config/yml/orm_quotestrategy.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    default_entity_manager: em1
    entity_managers:
        em1:
            mappings:
                XmlBundle: ~
            quote_strategy: doctrine.orm.quote_strategy.default
        em2:
            mappings:
                XmlBundle: ~
            quote_strategy: doctrine.orm.quote_strategy.ansi

File: tests/DependencyInjection/Fixtures/config/yml/orm_repository_factory.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    repository_factory: repository_factory

services:
repository_factory:
class: Doctrine\Bundle\DoctrineBundle\Repository\RepositoryFactory


File: tests/DependencyInjection/Fixtures/config/yml/orm_resolve_target_entity.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    resolve_target_entities:
        Symfony\Component\Security\Core\User\UserInterface: MyUserClass

File: tests/DependencyInjection/Fixtures/config/yml/orm_schema_ignore_classes.yml

doctrine:
dbal:
default_connection: default

text
orm:
    entity_managers:
        em1:
            schema_ignore_classes:
                - Class\A
                - Class\B

File: tests/DependencyInjection/Fixtures/config/yml/orm_second_level_cache.yml

services:
my_service_region_driver:
class: Symfony\Component\Cache\Adapter\ArrayAdapter

text
my_service_logger1:
    class: Doctrine\ORM\Cache\Logging\StatisticsCacheLogger

my_service_logger2:
    class: Doctrine\ORM\Cache\Logging\StatisticsCacheLogger

my_service_region:
    class: Doctrine\ORM\Cache\Region\DefaultRegion
    arguments: ["my_service_region", "@my_service_region_driver", 3600]

my_factory_config:
    class: Doctrine\ORM\Cache\CacheConfiguration

my_factory_driver:
    class: Symfony\Component\Cache\Adapter\ArrayAdapter

my_factory:
    class: Doctrine\ORM\Cache\DefaultCacheFactory
    arguments: ["@my_factory_config", "@my_factory_driver"]

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    entity_managers:
        custom_slc_factory:
            second_level_cache:
              factory: "my_factory"

        default:
            second_level_cache:
              log_enabled: true
              enabled: true
              region_cache_driver: ~

              loggers:
                  my_service_logger1 :
                    service: "my_service_logger1"

                  my_service_logger2 :
                    service: "my_service_logger1"

              regions:
                  my_service_region:
                    type: service
                    service : "my_service_region"

                  my_query_region:
                    lifetime: 300
                    cache_driver: ~
                    type: filelock
                    lock_path: "%kernel.cache_dir%/doctrine/orm/slc/filelock"

                  my_entity_region:
                      lifetime: 600
                      cache_driver: ~

File: tests/DependencyInjection/Fixtures/config/yml/orm_service_multiple_entity_managers.yml

doctrine:
dbal:
default_connection: conn1
connections:
conn1:
driver: pdo_sqlite
dbname: sqlite_db
user: sqlite_user
password: sqlite_s3cr3t
memory: true
conn2:
driver: pdo_sqlite
dbname: sqlite_db
user: sqlite_user
password: sqlite_s3cr3t
memory: true

text
orm:
    default_entity_manager: em2
    entity_managers:
        em1:
            connection: conn1
            mappings:
                XmlBundle: ~
        em2:
            connection: conn2
            mappings:
                XmlBundle: ~

File: tests/DependencyInjection/Fixtures/config/yml/orm_service_simple_single_entity_manager.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    default_entity_manager: default
    mappings:
        XmlBundle: ~

File: tests/DependencyInjection/Fixtures/config/yml/orm_service_simple_single_entity_manager_without_dbname.yml

doctrine:
dbal:
default_connection: default
connections:
default:

text
orm:
    default_entity_manager: default
    mappings:
        XmlBundle: ~

File: tests/DependencyInjection/Fixtures/config/yml/orm_service_single_entity_manager.yml

doctrine:
dbal:
default_connection: default
connections:
default:
driver: pdo_sqlite
dbname: sqlite_db
user: sqlite_user
password: sqlite_s3cr3t
memory: true

text
orm:
    default_entity_manager: default
    entity_managers:
        default:
            connection: default
            default_repository_class: Acme\Doctrine\Repository
            mappings:
                XmlBundle: ~

File: tests/DependencyInjection/Fixtures/config/yml/orm_single_em_bundle_mappings.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    validate_xml_mapping: true
    mappings:
        AttributesBundle:
            type: attribute
        XmlBundle:
            dir: Resources/config/doctrine
            alias: xml
        manual:
            type: xml
            prefix: Fixtures\Bundles\XmlBundle
            dir: "%kernel.root_dir%/tests/DependencyInjection/Fixtures/Bundles/XmlBundle/Resources/config/doctrine"
            alias: TestAlias

File: tests/DependencyInjection/Fixtures/config/yml/orm_single_em_default_table_options.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db
default_table_options:
charset: utf8mb4
collation: utf8mb4_unicode_ci
engine: InnoDB

text
orm:
    mappings:
        AttributesBundle: ~
        XmlBundle:
            dir: Resources/config/doctrine
            alias: xml
        manual:
            type: xml
            prefix: Fixtures\Bundles\XmlBundle
            dir: "%kernel.root_dir%/tests/DependencyInjection/Fixtures/Bundles/XmlBundle/Resources/config/doctrine"
            alias: TestAlias

File: tests/DependencyInjection/Fixtures/config/yml/orm_single_em_dql_functions.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    dql:
        string_functions:
            test_string: Doctrine\Bundle\DoctrineBundle\Tests\DependencyInjection\TestStringFunction

File: tests/DependencyInjection/Fixtures/config/yml/orm_typedfieldmapper.yml

doctrine:
dbal:
default_connection: default
connections:
default:
dbname: db

text
orm:
    default_entity_manager: default
    entity_managers:
        default:
            mappings:
                XmlBundle: ~
            typed_field_mapper: doctrine.orm.typed_field_mapper.default

File: tests/DependencyInjection/Fixtures/config/yml/well_known_schema_filter_default_tables_session.yml

doctrine:
dbal:
default_connection: connection1
connections:
connection1:
schema_filter: ^(?!t_)
connection2: []
connection3: []

services:
well_known_filter:
alias: 'doctrine.dbal.well_known_schema_asset_filter'
public: true

text
symfony.session:
    class: 'Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler'

File: tests/DependencyInjection/Fixtures/config/yml/well_known_schema_filter_overridden_tables_session.yml

doctrine:
dbal:
default_connection: connection1
connections:
connection1:
schema_filter: ^(?!t_)
connection2: []
connection3: []

services:
well_known_filter:
alias: 'doctrine.dbal.well_known_schema_asset_filter'
public: true

text
symfony.session:
    class: 'Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler'
    arguments:
        - ~
        - db_table: app_session

File: .github/dependabot.yml

version: 2
updates:

  • package-ecosystem: "github-actions"
    directory: "/"
    schedule:
    interval: "weekly"
    labels:
    • "CI"
      target-branch: "2.18.x"
      groups:
      doctrine:
      patterns:
      • "doctrine/*"

File: .github/FUNDING.yml

patreon: phpdoctrine
tidelift: packagist/doctrine%2Fdoctrine-bundle
custom: https://www.doctrine-project.org/sponsorship.html


File: .github/stale.yml

onlyLabels: ['Status: Waiting feedback']
daysUntilStale: 14
daysUntilClose: 7
staleLabel: 'Stale'
exemptProjects: true
exemptMilestones: true
markComment: >
This issue is still waiting on feedback. Please provide the information requested above to allow us to continue working on this ticket.

This issue will be closed after 7 days. You can still provide us with the necessary information to continue working on this issue, and we will reopen the ticket for you. Thanks!


File: .github/workflows/coding-standards.yml

name: "Coding Standards"

on:
pull_request:
branches:
- ".x"
paths:
- .github/workflows/coding-standards.yml
- config/
*
- composer.*
- phpcs.xml.dist
- src/**
- tests/**
push:
branches:
- ".x"
paths:
- .github/workflows/coding-standards.yml
- config/
*
- composer.*
- phpcs.xml.dist
- src/**
- tests/**

jobs:
coding-standards:
name: "Coding Standards"
uses: "doctrine/.github/.github/workflows/[email protected]"
with:
composer-options: "--prefer-dist --prefer-stable"


File: .github/workflows/composer-lint.yml

name: "Composer Lint"

on:
pull_request:
branches:
- ".x"
paths:
- .github/workflows/composer-lint.yml
- "composer.json"
push:
branches:
- "
.x"
paths:
- .github/workflows/composer-lint.yml
- "composer.json"

jobs:
composer-lint:
name: "Composer Lint"
uses: "doctrine/.github/.github/workflows/[email protected]"


File: .github/workflows/continuous-integration.yml

name: "CI: PHPUnit"

on:
pull_request:
branches:
- ".x"
paths:
- .github/workflows/continuous-integration.yml
- config/
*
- composer.*
- phpunit.xml.dist
- src/**
- templates/**
- tests/**
push:
branches:
- ".x"
paths:
- .github/workflows/continuous-integration.yml
- config/
*
- composer.*
- phpunit.xml.dist
- src/**
- templates/**
- tests/**

jobs:
phpunit:
name: >
${{ format('PHP {0} - Sf {1} - deps {2} - stab. {3}',
matrix.php-version || 'Ø',
matrix.symfony-require || 'Ø',
matrix.dependencies || 'Ø',
matrix.stability || 'Ø'
) }}
${{ matrix.remove-orm && ' - remove ORM' }}
${{ matrix.remove-doctrine-messenger && ' - remove Messenger' }}
runs-on: "ubuntu-latest"
env:
SYMFONY_REQUIRE: ${{matrix.symfony-require}}
SYMFONY_DEPRECATIONS_HELPER: weak

text
strategy:
  fail-fast: false
  matrix:
    php-version:
      - "8.4"
    dependencies:
      - "highest"
    stability:
      - "stable"
    symfony-require:
      - ""
    remove-orm:
      - false
    remove-doctrine-messenger:
      - false
    include:
      # Tests the lowest set of dependencies
      - dependencies: "lowest"
        stability: "stable"
        php-version: "8.4"

      # Test legacy LTS
      - symfony-require: "6.4.*"
        dependencies: "highest"
        php-version: "8.5"

      # Test LTS
      - symfony-require: "7.4.*"
        dependencies: "highest"
        php-version: "8.5"

      # Test non-LTS
      - symfony-require: "8.0.*"
        dependencies: "highest"
        php-version: "8.5"

      # DBAL only without ORM
      - php-version: "8.5"
        dependencies: "highest"
        stability: "stable"
        remove-orm: true

      # No Messenger integration
      - php-version: "8.5"
        dependencies: "highest"
        stability: "stable"
        remove-doctrine-messenger: true

      # Bleeding edge
      - php-version: "8.5"
        dependencies: "highest"
        stability: "dev"

steps:
  - name: "Checkout"
    uses: "actions/checkout@v7"
    with:
      fetch-depth: 2

  - name: "Install PHP with PCOV"
    uses: "shivammathur/setup-php@v2"
    with:
      php-version: "${{ matrix.php-version }}"
      coverage: "pcov"
      ini-file: "development"
      extensions: "pdo_sqlite"
      tools: "flex"

  - name: "Enforce using stable dependencies"
    run: "composer config minimum-stability stable"
    if: "${{ matrix.stability == 'stable' }}"

  - name: "Remove doctrine/orm"
    run: "composer remove doctrine/orm --dev --no-update"
    if: "${{ matrix.remove-orm }}"

  - name: "Remove symfony/doctrine-messenger"
    run: "composer remove symfony/doctrine-messenger --dev --no-update"
    if: "${{ matrix.remove-doctrine-messenger }}"

  - name: "Install dependencies with Composer"
    uses: "ramsey/composer-install@v4"
    with:
      dependency-versions: "${{ matrix.dependencies }}"
      composer-options: "--prefer-dist"

  - name: "Run PHPUnit"
    run: "vendor/bin/phpunit --coverage-clover=coverage.xml"

  - name: "Upload coverage file"
    uses: "actions/upload-artifact@v7"
    with:
      name: "phpunit-${{ matrix.php-version }}-${{ matrix.dependencies }}-${{ hashFiles('composer.lock') }}.coverage"
      path: "coverage.xml"

upload_coverage:
name: "Upload coverage to Codecov"
runs-on: "ubuntu-latest"
# Only run on PRs from forks or PRs from branches that do not match *.x
if: "github.event.pull_request.head.repo.full_name != github.repository || !contains(github.event.pull_request.head.ref, '.x')"
needs:
- "phpunit"

text
steps:
  - name: "Checkout"
    uses: "actions/checkout@v7"
    with:
      fetch-depth: 2

  - name: "Download coverage files"
    uses: "actions/download-artifact@v8"
    with:
      path: "reports"

  - name: "Upload to Codecov"
    uses: "codecov/codecov-action@v7"
    with:
      directory: reports
    env:
      CODECOV_TOKEN: "${{ secrets.CODECOV_TOKEN }}"

File: .github/workflows/documentation.yml

name: "Documentation"

on:
pull_request:
branches:
- ".x"
paths:
- ".github/workflows/documentation.yml"
- "docs/**"
push:
branches:
- "
.x"
paths:
- ".github/workflows/documentation.yml"
- "docs/**"

jobs:
documentation:
name: "Documentation"
uses: "doctrine/.github/.github/workflows/[email protected]"


File: .github/workflows/release-on-milestone-closed.yml

name: "Automatic Releases"

on:
milestone:
types:
- "closed"

jobs:
release:
name: "Git tag, release & create merge-up PR"
uses: "doctrine/.github/.github/workflows/[email protected]"
secrets:
GIT_AUTHOR_EMAIL: ${{ secrets.GIT_AUTHOR_EMAIL }}
GIT_AUTHOR_NAME: ${{ secrets.GIT_AUTHOR_NAME }}
ORGANIZATION_ADMIN_TOKEN: ${{ secrets.ORGANIZATION_ADMIN_TOKEN }}
SIGNING_SECRET_KEY: ${{ secrets.SIGNING_SECRET_KEY }}


File: .github/workflows/static-analysis.yml

name: "Static Analysis"

on:
pull_request:
branches:
- ".x"
paths:
- .github/workflows/static-analysis.yml
- config/
*
- composer.*
- phpstan.neon.dist
- src/**
- tests/**
push:
branches:
- ".x"
paths:
- .github/workflows/static-analysis.yml
- config/
*
- composer.*
- phpstan.neon.dist
- src/**
- tests/**

jobs:
static-analysis:
name: "PHPStan"
runs-on: "ubuntu-latest"

text
steps:
  - name: "Checkout code"
    uses: "actions/checkout@v5"

  - name: "Install PHP"
    uses: "shivammathur/setup-php@v2"
    with:
      coverage: "none"
      php-version: "8.4"

  - name: "Install dependencies with Composer"
    uses: "ramsey/composer-install@v3"

  - name: "Warm up Symfony cache"
    run: "php tests/console-application.php"

  - name: "Run a static analysis with phpstan/phpstan"
    run: "vendor/bin/phpstan analyse -v"

File: .github/workflows/test-dev-stability.yml

name: "Dev dependencies stability check"

on:
schedule:
- cron: "0 0 * * 0"

jobs:
phpunit:
name: "PHPUnit"
runs-on: "ubuntu-latest"
env:
SYMFONY_REQUIRE: ${{matrix.symfony-require}}

text
strategy:
  fail-fast: false
  matrix:
    php-version:
      - "8.4"
    dependencies:
      - "highest"
    stability:
      - "dev"
    symfony-require:
      - ""
      - "6.*"

steps:
  - name: "Checkout"
    uses: "actions/checkout@v7"
    with:
      fetch-depth: 2

  - name: "Install PHP"
    uses: "shivammathur/setup-php@v2"
    with:
      php-version: "${{ matrix.php-version }}"
      ini-file: "development"
      extensions: "pdo_sqlite"
      tools: "flex"

  - name: "Install dependencies with Composer"
    uses: "ramsey/composer-install@v4"
    with:
      dependency-versions: "${{ matrix.dependencies }}"
      composer-options: "--prefer-dist"

  - name: "Run PHPUnit"
    run: "vendor/bin/phpunit"

File: .github/workflows/website-schema.yml

name: "Website config validation"

on:
pull_request:
branches:
- ".x"
paths:
- ".doctrine-project.json"
- ".github/workflows/website-schema.yml"
push:
branches:
- "
.x"
paths:
- ".doctrine-project.json"
- ".github/workflows/website-schema.yml"

jobs:
json-validate:
name: "Validate JSON schema"
uses: "doctrine/.github/.github/workflows/[email protected]"