Как обрабатывать миграции с помощью нескольких диспетчеров сущностей в DoctrineMigrationsBundle 3

В doctrine/doctrine-migrations-bundle 2.* это было относительно просто — используйте опцию --em (и используйте ContainerAwareInterface, чтобы пропустить любые миграции из другого em/соединения).

Теперь (на doctrine/doctrine-migrations-bundle 3.2.2) кажется, что опция --em игнорируется, и всегда указывается em/connection по умолчанию, что означает, что миграции для em по умолчанию применяются к каждой базе данных. Редактировать: как указано в комментариях - --em не игнорируется, он передается напрямую, это скорее наш ContainerAwareInterface подход, который больше не действует.

Существует много противоречивой информации о том, как это настроить, некоторые предполагают, что это должно «просто работать» (документы Symfony), а другие описывают обходные пути (проблема):

https://symfony.com/doc/current/doctrine/multiple_entity_managers.htmlhttps://github.com/doctrine/DoctrineMigrationsBundle/issues/38

Как настроить эту новую версию (3) doctrine/doctrine-migrations-bundle для применения миграций только к соответствующему объекту/базе данных?

Обновлено: я включил ниже нашу конфигурацию перед обновлением, которая, наряду с подходом к фильтрации соединений ContainerAwareInterface, позволяла выполнять фильтрацию миграции только для соответствующего менеджера объектов.

Наша существующая конфигурация "doctrine/doctrine-bundle": "1.12.8" (сокращена, но показывает несколько менеджеров сущностей):

doctrine:
    dbal:
        connections:
            default:
                charset: utf8mb4
                default_table_options:
                    charset: utf8mb4
                    collate: utf8mb4_unicode_ci
                driver: '%database_driver%'
                server_version: mariadb-10.4.11
                host: '%database_host%'
                port: '%database_port%'
                dbname: autotempest
                user: '%database_user%'
                password: '%database_password%'
                mapping_types:
                    enum: string
            model:
                charset: utf8mb4
                default_table_options:
                    charset: utf8mb4
                    collate: utf8mb4_unicode_ci
                driver: '%database_driver%'
                server_version: mariadb-10.4.11
                host: '%database_host%'
                port: '%database_port%'
                dbname: autotempest_models
                user: '%database_user%'
                password: '%database_password%'
                mapping_types:
                    enum: string
                wrapper_class: App\Doctrine\ConnectionWrapper\ConnectionModel
            persistent: true

    orm:
        auto_generate_proxy_classes: '%kernel.debug%'
        entity_managers:
            default:
                connection: default
                mappings:
                    App:
                        type: 'annotation'
                        dir: '%kernel.project_dir%/src/Entity/Main'
                        prefix: 'App\Entity\Main'
            model:
                connection: model
                mappings:
                    TempestModelBundle:
                        type: 'annotation'
                        dir: 'Entity'
                        prefix: 'Tempest\Bundle\ModelBundle\Entity'

Наш "doctrine/doctrine-migrations-bundle": "2.1.2" конфиг:

doctrine_migrations:
    dir_name: '%kernel.project_dir%/src/Migrations'
    namespace: Application\Migrations

Пожалуйста, обновите свой вопрос, чтобы включить конфигурации для вашей доктрины и настроек миграции.

Will B. 07.04.2022 06:57

Для общей справки: все, что делает doctrine/doctrine-migrations-bundle, — это регистрирует команды в symfony на основе классов в doctrine/migrations, которые расширяют DoctrineCommand.

Will B. 07.04.2022 07:13

@УиллБ. спасибо, я добавил наш существующий config. Re: что делает doctrine/doctrine-migrations-bundle — это еще и предоставляет параметр конфигурации services, который нам нужен для того, чтобы внедрять сервисы в наши миграции через MigrationFactory.

Matt Bennett 08.04.2022 17:14

Я имел в виду создание или соблюдение параметров консольной команды, таких как --em. Пакет не переопределяет их из DoctrineCommand, который вызывает $this->dependencyFactory->getConfiguration()->setEntityManag‌​erName($emName);, когда указана опция --em. Пакет создает услугу DependencyFactory, передаваемую DoctrineCommand, на основе вашего Конфигурация Symfony.

Will B. 08.04.2022 17:44

Ах, спасибо за разъяснение. У этой проблемы было несколько уровней, но в основном она основывалась на том факте, что миграция с учетом контейнера больше не является хорошим подходом для реализации поддержки нескольких менеджеров сущностей. Однако мы пришли к решению, которое работает для нас на данный момент.

Matt Bennett 08.04.2022 17:55

Я считаю, что проблема связана с TempestModelBundle.mappings.dir: 'Entity' вашего model EntityManager, поскольку он использует тот же пользователь/пароль подключения, а не ссылается на абсолютный путь явного пространства имен %kernel.project_dir%/src/Tempest/Bundle/ModelBundle/Entity.

Will B. 08.04.2022 18:35

Конфигурация, которую я разместил в своем вопросе, отлично работает в версиях, которые я там упомянул. Моя проблема заключалась в том, чтобы выяснить, как перенести его на новые версии. Я ответил рабочим подходом, который мы использовали ниже (который использует ту же конфигурацию doctrine, что и выше, просто требуется другой подход для миграции).

Matt Bennett 08.04.2022 19:08
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
7
47
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Также в моем вопросе упоминается открытая проблема DoctrineMigrationsBundle от 2012 года, описывающая проблему миграции при использовании нескольких менеджеров сущностей: https://github.com/doctrine/DoctrineMigrationsBundle/issues/38. Кажется, есть несколько вариантов решения этой проблемы, как описано там, нам просто нужно было покопаться и попробовать каждый из них, чтобы найти лучший для нашей ситуации.

Миграция с учетом контейнеров

В Symfony 3 мы использовали подход ContainerAwareInterface. Описано в предыдущем выпуске:

Currently this can be achieved by using Container Aware Migrations. If one can have the service container injected, he can obtain an instance of some entity manager and its connection.

Однако это больше не является правильным решением при переходе на Symfony 4 из-за того, что классы ContainerAware устарели в пользу внедрения зависимостей.

Передать конфигурацию напрямую

Другой подход, упомянутый в проблеме github выше. Идея здесь состоит в том, чтобы иметь отдельный файл конфигурации для каждого менеджера сущностей, как показано ниже:

# config/packages/migrations/base.yaml
em: default
transactional: false
migrations_paths:
    Hyra\Migrations\Base: src/Migrations/Base
table_storage:
    table_name: migration_versions

Это передается непосредственно в команду вместе с менеджером сущностей следующим образом: bin/console doctrine:migrations:migrate --em default --configuration config/packages/migrations/base.yaml. Эти отдельные файлы конфигурации заменяют один файл конфигурации config/packages/doctrine_migrations.yaml.

Это также было нецелесообразно для нас, так как нам все еще нужно было внедрять сервисы в наши миграции, используя параметр конфигурации services для DoctrineMigrationsBundle, а --configuration передает параметры конфигурации только напрямую в doctrine/migrations, который не поддерживает параметр конфигурации services.

Изначально на DoctrineMigrationsBundle 3.0 этот подход усложнялся тем, что опции --em и --conn были полностью отброшены, поэтому также необходимо было создать обертку поверх команд DoctrineMigrationsBundle для повторной реализации этих опций (более подробно описано здесь). В этом больше нет необходимости в DoctrineMigrationsBundle 3.1+ (который восстановил эти параметры).

Используйте DoctrineMigrationsMultipleDatabaseBundle

Также упомянутый в ветке проблем github, этот пакет реализует именно то, что нам было нужно (и в конечном итоге использовали) — конфигурацию для каждого объекта для DoctrineMigrationsBundle, поэтому мы также можем включить нашу конфигурацию services для внедрения зависимостей миграции. Изначально я неправильно настроил это — важно, чтобы базовая конфигурация doctrine_migrations.yaml включала только конфигурацию для менеджера сущностей по умолчанию. Пример рабочей конфигурации предоставлен автором пакета (версия 0.3.3):

# doctrine.yaml
doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                url: '%env(resolve:DATABASE_URL)%'
                server_version: mariadb-10.1.26
                charset: utf8mb4
                default_table_options:
                    charset: utf8mb4
                    collate: utf8mb4_unicode_ci
                mapping_types:
                    enum: string
            geonames:
                url: '%env(resolve:GEONAMES_DATABASE_URL)%'
                server_version: mariadb-10.1.26
                charset: utf8mb4
                default_table_options:
                    charset: utf8mb4
                    collate: utf8mb4_unicode_ci
                mapping_types:
                    enum: string

        # IMPORTANT: You MUST configure your server version,
        # either here or in the DATABASE_URL env var (see .env file)
        #server_version: '5.7'
    orm:
        auto_generate_proxy_classes: true
        default_entity_manager: default
        entity_managers:
            default:
                connection: default
                naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
                mappings:
                    Main:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/App/Entity/Main'
                        prefix: 'App\Entity\Main'
                        alias: Main
            geonames:
                naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
                connection: geonames
                mappings:
                    Geonames:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/App/Entity/Geonames'
                        prefix: 'App\Entity\Geonames'
                        alias: Geonames
# doctrine_migrations.yaml
doctrine_migrations:
    em: default
    migrations_paths:
        DoctrineMigrations: '%kernel.project_dir%/migrations/Main'
# doctrine_migrations_multiple_database.yaml
doctrine_migrations_multiple_database:
    entity_managers:
        default:
            migrations_paths:
                DoctrineMigrations\Main: '%kernel.project_dir%/migrations/Main'
        geonames:
            migrations_paths:
                DoctrineMigrations\Geonames: '%kernel.project_dir%/migrations/Geonames'

Другие вопросы по теме