kraz/doctrine-context-bundle

Symfony bundle for working with multiple databases via doctrine entity manager or connection.

Maintainers

Package info

github.com/kraz/doctrine-context-bundle

Type:symfony-bundle

pkg:composer/kraz/doctrine-context-bundle

Statistics

Installs: 10

Dependents: 0

Suggesters: 0

Stars: 2

Open Issues: 0

3.9.15 2026-04-15 16:08 UTC

README

CI Packagist Version GitHub license

A Symfony bundle that makes working with multiple Doctrine entity managers or DBAL connections painless. It wraps the standard Doctrine commands so that a single command can target one specific context or fan out across all of them automatically. The only hard dependency is doctrine/dbal - ORM and Migrations support are both optional.

The problem

When a project has more than one entity manager or DBAL connection, running the same operation across all of them requires repeating the command manually once per context:

php bin/console doctrine:migrations:migrate --em=shop
php bin/console doctrine:migrations:migrate --em=analytics
php bin/console doctrine:migrations:migrate --em=audit

There is also a subtle schema-pollution problem: after running migrations, doctrine:schema:update and doctrine:schema:validate see the migration metadata table (e.g. doctrine_migration_versions) as an unmanaged table and report it as something to drop or as a validation error.

What this bundle does

  • Database command integration

    The command doctrine:database:create fans out across all registered contexts. Works with DBAL alone - no ORM or Migrations required. Accepts --connection / --conn to target a single context and --connections / --conns to target a specific subset.

  • Migrations command integration

    requires doctrine/doctrine-migrations-bundle

    Every doctrine:migrations:* command gains --em / --ems and --conn / --conns options. Pass one to target a single context or a subset, or omit all to run across every registered context in sequence.

  • ORM command integration

    requires doctrine/orm

    The doctrine:schema:create, doctrine:schema:validate, and doctrine:mapping:info receive the same fan-out behaviour, including --em / --ems for subset selection.

  • Schema filter

    The migration metadata table remains hidden for commands like doctrine:schema:update and doctrine:schema:validate, so those commands never see it as unmanaged.

  • Additional command options for every wrapped command

    • --ctx-isolation: When set, a failure in one context does not abort the remaining contexts.
    • --ctx-all: Explicitly runs the command over all registered contexts. Required when explicit_context is enabled and no specific context is given.
    • --ctx-output-style: Control how the context name is being printed to the output.
  • Bundle configurations about commands execution behavior

    • explicit_context: When true, every wrapped command requires an explicit context via --em, --ems, --conn, --conns, --connection, --connections, or --ctx-all. Prevents accidental fan-out in production environments.

Requirements

Dependency Version
PHP >= 8.4
doctrine/doctrine-bundle ^3.2
doctrine/doctrine-migrations-bundle ^4.0 (optional)
doctrine/orm ^3.6 (optional)

Installation

composer require kraz/doctrine-context-bundle

Register the bundle in config/bundles.php if you are not using Symfony Flex:

return [
    // ...
    Kraz\DoctrineContextBundle\DoctrineContextBundle::class => ['all' => true],
];

Configuration

Register each entity manager or connection that should be treated as a named context. You may use entity_managers (requires doctrine/orm) or connections, but not both for the same name.

The migration-related options (migrations_paths, storage, services, etc.) are only available when doctrine/doctrine-migrations-bundle is installed. Without it, a context is configured with just its name.

DBAL only (no ORM, no Migrations)

# config/packages/doctrine_context.yaml
doctrine_context:
    connections:
        default: ~
        shop: ~
        analytics: ~

With DBAL connections and Migrations

doctrine_context:
    connections:
        default:
            migrations_paths:
                App\Migrations\Default: '%kernel.project_dir%/migrations/default'
            storage:
                table_storage:
                    table_name: doctrine_migration_versions
        shop:
            migrations_paths:
                App\Migrations\Shop: '%kernel.project_dir%/migrations/shop'
            storage:
                table_storage:
                    table_name: doctrine_migration_versions

With entity managers (ORM) and Migrations

doctrine_context:
    entity_managers:
        default:
            migrations_paths:
                App\Migrations\Default: '%kernel.project_dir%/migrations/default'
            storage:
                table_storage:
                    table_name: doctrine_migration_versions
        shop:
            migrations_paths:
                App\Migrations\Shop: '%kernel.project_dir%/migrations/shop'
            storage:
                table_storage:
                    table_name: doctrine_migration_versions
        analytics:
            migrations_paths:
                App\Migrations\Analytics: '%kernel.project_dir%/migrations/analytics'
            storage:
                table_storage:
                    table_name: doctrine_migration_versions

With entity managers (ORM), no Migrations

doctrine_context:
    entity_managers:
        default: ~
        shop: ~
        analytics: ~

Requiring explicit context selection

Set explicit_context: true to prevent any wrapped command from fanning out over all contexts unless the caller deliberately opts in with --ctx-all. Every invocation must target a specific context or pass --ctx-all explicitly, making accidental mass operations impossible.

doctrine_context:
    explicit_context: true
    entity_managers:
        default: ~
        shop: ~
        analytics: ~

With this option active, the following is an error:

# Error: Explicit context is required. Specify a context via --em, --ems, --conn, --conns, or use --ctx-all to run over all contexts.
php bin/console doctrine:migrations:migrate --no-interaction

Provide a context or opt into all:

# Single context
php bin/console doctrine:migrations:migrate --em=shop --no-interaction

# Subset of contexts
php bin/console doctrine:migrations:migrate --ems=shop,analytics --no-interaction

# All contexts, intentionally
php bin/console doctrine:migrations:migrate --ctx-all --no-interaction

Full configuration reference

The migration-related keys below are only accepted when doctrine/doctrine-migrations-bundle is installed.

doctrine_context:
    explicit_context: false     # when true, --em/--ems/--conn/--conns/--connection/--connections or --ctx-all is required
    entity_managers:           # or connections:
        <name>:
            migrations_paths:
                <Namespace>: <path>
            migrations:        # individual migration classes to load
                - App\Migrations\SpecialMigration
            storage:
                table_storage:
                    table_name: doctrine_migration_versions
                    version_column_name: ~
                    version_column_length: ~
                    executed_at_column_name: ~
                    execution_time_column_name: ~
            services:          # override doctrine/migrations services
                Doctrine\Migrations\SomeService: my_symfony_service_id
            factories:         # override doctrine/migrations services via callables
                Doctrine\Migrations\SomeService: my_factory_service_id
            all_or_nothing: false
            check_database_platform: true
            custom_template: ~
            organize_migrations: false  # false | BY_YEAR | BY_YEAR_AND_MONTH

Usage

Run migrations for all contexts

Omitting --em / --conn fans the command out across every registered context:

php bin/console doctrine:migrations:migrate --no-interaction

Output will be grouped by context:

Entity Manager: default
-----------------------

 [notice] Migrating up to ...
  
Entity Manager: shop
--------------------

 [notice] Migrating up to ...

Entity Manager: analytics
-------------------------
 
 [notice] No migrations to execute.

Target a specific context

# entity manager
php bin/console doctrine:migrations:migrate --em=shop --no-interaction

# DBAL connection
php bin/console doctrine:migrations:migrate --conn=shop --no-interaction

Target a subset of contexts

Use the plural form of each option to pass multiple context names. Values can be supplied as separate arguments or as a comma-separated list - both forms are equivalent and may be combined:

# Separate arguments
php bin/console doctrine:migrations:migrate --ems=shop --ems=analytics --no-interaction

# Comma-separated (same result)
php bin/console doctrine:migrations:migrate --ems=shop,analytics --no-interaction

# DBAL connections
php bin/console doctrine:migrations:migrate --conns=shop,analytics --no-interaction

# ORM schema commands
php bin/console doctrine:schema:create --ems=shop,analytics
Option Plural / multi-value form Applicable commands
--em --ems ORM and migration commands
--conn --conns Migration and database commands
--connection --connections Database commands

Continue past failures with --ctx-isolation

By default, a failure in one context stops execution when executed in non-interactive mode. Use --ctx-isolation to continue with the remaining contexts regardless:

php bin/console doctrine:migrations:migrate --no-interaction --ctx-isolation

Run over all contexts explicitly with --ctx-all

--ctx-all behaves identically to omitting a specific context (fans out over every registered context), but makes the intent explicit. It is required when explicit_context: true is configured and no specific context is given:

php bin/console doctrine:migrations:migrate --ctx-all --no-interaction
php bin/console doctrine:database:create --ctx-all

Create databases

# All contexts
php bin/console doctrine:database:create

# All contexts, explicitly
php bin/console doctrine:database:create --ctx-all

# Specific context – all four flags are equivalent
php bin/console doctrine:database:create --connection=shop
php bin/console doctrine:database:create --conn=shop

# Subset of contexts – all four flags are equivalent
php bin/console doctrine:database:create --connections=shop,analytics
php bin/console doctrine:database:create --conns=shop,analytics

All supported commands

Always available (DBAL only):

Command Description
doctrine:database:create Create the database for each registered context

When doctrine/doctrine-migrations-bundle is installed:

Command Description
doctrine:migrations:migrate Execute migrations
doctrine:migrations:diff Generate a migration by diffing the schema
doctrine:migrations:generate Generate a blank migration class
doctrine:migrations:execute Execute or revert a specific migration
doctrine:migrations:status Show the migration status
doctrine:migrations:list List available migrations
doctrine:migrations:current Show the current migration version
doctrine:migrations:latest Show the latest available version
doctrine:migrations:up-to-date Check if the schema is up to date
doctrine:migrations:rollup Roll up migrations into a single version
doctrine:migrations:version Manually add/delete versions from the table
doctrine:migrations:dump-schema Dump the schema for a mapping
doctrine:migrations:sync-metadata-storage Sync the metadata storage

When doctrine/orm is installed:

Command Description
doctrine:schema:create Create schema across all entity managers
doctrine:schema:validate Validate schema across all entity managers
doctrine:mapping:info Show mapping info across all entity managers

Schema filter

When doctrine/doctrine-migrations-bundle is installed, the bundle automatically registers a DBAL schema filter per context that hides the migration metadata table from doctrine:schema:update and doctrine:schema:validate. This prevents those commands from flagging the migration table as an unmanaged or extra table.

The filter activates only during schema update/validate commands and is otherwise transparent.

Acknowledgements

The idea behind this bundle is credited to DoctrineMigrationsMultipleDatabaseBundle which was heavily refactored to support Symfony 8 and some functional enhancements.

License

This bundle is licensed under the MIT License. See the LICENSE file for details.