# Technical Documentation: doctrine/DoctrineBundle

> ℹ️ **Provenance:** In-Tree Documentation (85 Chapters) · [CodeWiki Reference](https://codewiki.google/github.com/doctrine/DoctrineBundle) · Recency: Active (< 180 days)

## File: README.md

# Doctrine Bundle

Doctrine DBAL & ORM Bundle for the Symfony Framework.

[](https://github.com/doctrine/DoctrineBundle/actions/workflows/continuous-integration.yml)
[](https://codecov.io/gh/doctrine/DoctrineBundle)

## 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](https://symfony.com/doc/current/reference/configuration/doctrine.html).
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": "fabien@symfony.com"
        },
        {
            "name": "Benjamin Eberlei",
            "email": "kontakt@beberlei.de"
        },
        {
            "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](https://www.doctrine-project.org/policies/security.html#reporting).

Security vulnerabilities should be reported to security@doctrine-project.org
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 `MappingException`s 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.

### Proxy-related configuration settings are conditionally deprecated

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

    <?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

    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::

    .. 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

    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

    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

    <?php
    // User.php

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

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

.. configuration-block::

    .. 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::

    .. 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::

    .. 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::

    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

    $ 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::

    <?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::

    <?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`_:

    "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

    <?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

    <?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

    <?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

    <?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::

    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

    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 }

    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

    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

    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'

    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

    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

    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

    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

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

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

    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

    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

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

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

    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

    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

    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

    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

    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

    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

    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

    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

    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

    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

    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

    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

    orm:
        enable_native_lazy_objects: true

---

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

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

    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

    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

    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

    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

    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

    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

    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

    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:

    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

    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

    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

    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

    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

    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

    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

    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/coding-standards.yml@15.1.0"
    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/composer-lint.yml@15.1.0"

---

## 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

    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"

    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/documentation.yml@15.1.0"

---

## 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/release-on-milestone-closed.yml@15.1.0"
    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"

    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}}

    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/website-schema.yml@15.1.0"

--- METRICS ---
- Files Extracted: 85
- Estimated Token Budget: ~18157 tokens
- Recency Window: Active (< 180 days)
- Canonical Reference: https://codewiki.google/github.com/doctrine/DoctrineBundle
