Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Doctrine Multibase Bundle Laravel Package

gam6itko/doctrine-multibase-bundle

A Symfony bundle that adds multi-database support to Doctrine ORM: configure several connections and assign entities to them via attributes, letting a single application persist to and query from multiple databases.

View on GitHub
Deep Wiki
Context7

Getting Started

This bundle is small and underexposed (no stars, no dependents), so treat the source as the documentation. The core idea: keep your default Doctrine connection as the "base", and at runtime repoint it at a different database instance without rebuilding the container.

Minimal steps:

  1. composer require gam6itko/doctrine-multibase-bundle
  2. Register Gam6itko\DoctrineMultibaseBundle\DoctrineMultibaseBundle in config/bundles.php
  3. Declare your candidate databases as ordinary DBAL connections — the bundle switches which one the base connection resolves to, not the entity managers:
# config/packages/doctrine.yaml
doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                url: '%env(DATABASE_URL)%'
            reporting:
                url: '%env(REPORTING_DATABASE_URL)%'
            tenant_a:
                url: '%env(TENANT_A_DATABASE_URL)%'
  1. Find the switching entry point. Look in src/ for the class that decorates or extends Doctrine\DBAL\Connection, and in Resources/config/ (services.xml/yaml) for the service ID it replaces (usually doctrine.dbal.default_connection or a new multibase.connection alias). Grep for switch, selectBase, or setConnection to see the exact method name — it is not standardized.

First use case to validate your integration: a console command or controller that hits $connection->getDatabase() (or SELECT DATABASE()), switches to reporting, and confirms the query now lands on the other schema. Once that works, the rest is just deciding when to switch.

Implementation Patterns

Request-scoped switching via a listener. The most common pattern is a kernel.request subscriber that resolves a tenant/report target and calls the switch before anything touches the EM. Keep the decision in one place so controllers never call the switch method directly.

Wrap switches in try/finally. Because the switch mutates a shared service, always restore the base connection:

$previous = $connection->getDatabase();
try {
    $connection->switchTo('reporting');   // confirm method name in src/
    $rows = $connection->fetchAllAssociative($sql);
} finally {
    $connection->switchTo($previous);
}

Expose this as a small MultibaseManager service (switch + restore + current()) and inject that everywhere instead of the raw connection — it makes the lifecycle explicit and testable.

Console commands. Call the switch at the top of execute() against the connection the command receives, and add a --base= option. This lets one command target any configured DB without duplicating command classes.

Messenger / long-running workers. Switch per message, not per worker boot, and restore in finally. A stale base leaking into the next message is the classic production bug for this kind of bundle.

Testing. Point a test connection at SQLite or a throwaway schema and switch in setUp(); restore in tearDown(). Keep the switch out of fixtures so you don't accidentally seed the wrong base.

Gotchas and Tips

  • Close before you switch. If the wrapper reuses the underlying PDO, you may still be talking to the old server. Look for a close() call inside the switch method or call it yourself; verify with SELECT DATABASE() after switching.
  • Metadata cache is per entity manager, not per connection. Doctrine caches mapping metadata by class name. If two bases have divergent schemas, switching connections will happily reuse the wrong metadata. Clear with $em->getMetadataFactory()->setMetadataFor(...) or use separate EMs per base.
  • Identity map / UnitOfWork contamination. Entities loaded from base A remain managed after you switch to base B. Call $em->clear() on switch (or on restore) to avoid saving stale objects into the wrong database.
  • Transactions are per connection. Never switch inside an open transaction — beginTransaction() / commit() will hit different PDO objects. Assert !$connection->isTransactionActive() in your manager's switch method.
  • Migrations and schema tools ignore the runtime switch unless you invoke them after switching. doctrine:migrations:migrate defaults to default; pass --em/--conn per base or wrap in a loop that switches first.
  • DBAL version drift. The internals of Doctrine\DBAL\Connection changed substantially between 2.x and 3.x (constructor signature, fetchAllAssociative vs fetchAll). A 0-star bundle is unlikely to cover both — check composer.json constraints before adopting, and pin DBAL accordingly.
  • Persistent connections. PDO::ATTR_PERSISTENT can survive a switch within one PHP-FPM process and serve stale data. Disable persistence on connections you switch.
  • Debugging. Log the current base on every switch (a one-line info with the previous and new base pays for itself), and rely on the Symfony profiler's Doctrine panel — it shows the connection name, which makes a mis-switch obvious.
  • Extension point. If the bundle's switch method is too coarse, decorate the connection service in your own services.yaml and add the guardrails (transaction check, clear(), logging) in your decorator rather than patching vendor code.
  • Vendor risk. With no stars and no dependents, budget time to read every line of src/ and to fork/pin. Assume you own maintenance of it.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo