В 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
Для общей справки: все, что делает doctrine/doctrine-migrations-bundle
, — это регистрирует команды в symfony на основе классов в doctrine/migrations
, которые расширяют DoctrineCommand
.
@УиллБ. спасибо, я добавил наш существующий config. Re: что делает doctrine/doctrine-migrations-bundle
— это еще и предоставляет параметр конфигурации services
, который нам нужен для того, чтобы внедрять сервисы в наши миграции через MigrationFactory
.
Я имел в виду создание или соблюдение параметров консольной команды, таких как --em
. Пакет не переопределяет их из DoctrineCommand
, который вызывает $this->dependencyFactory->getConfiguration()->setEntityManagerName($emName);
, когда указана опция --em
. Пакет создает услугу DependencyFactory
, передаваемую DoctrineCommand
, на основе вашего Конфигурация Symfony.
Ах, спасибо за разъяснение. У этой проблемы было несколько уровней, но в основном она основывалась на том факте, что миграция с учетом контейнера больше не является хорошим подходом для реализации поддержки нескольких менеджеров сущностей. Однако мы пришли к решению, которое работает для нас на данный момент.
Я считаю, что проблема связана с TempestModelBundle.mappings.dir: 'Entity'
вашего model
EntityManager, поскольку он использует тот же пользователь/пароль подключения, а не ссылается на абсолютный путь явного пространства имен %kernel.project_dir%/src/Tempest/Bundle/ModelBundle/Entity
.
Конфигурация, которую я разместил в своем вопросе, отлично работает в версиях, которые я там упомянул. Моя проблема заключалась в том, чтобы выяснить, как перенести его на новые версии. Я ответил рабочим подходом, который мы использовали ниже (который использует ту же конфигурацию doctrine
, что и выше, просто требуется другой подход для миграции).
Также в моем вопросе упоминается открытая проблема 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'
Пожалуйста, обновите свой вопрос, чтобы включить конфигурации для вашей доктрины и настроек миграции.