PHPackages                             feroz/dynamic-db-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. feroz/dynamic-db-bundle

ActiveSymfony-bundle[Database &amp; ORM](/categories/database)

feroz/dynamic-db-bundle
=======================

Symfony bundle to manage dynamic database connections using Doctrine ORM.

0.0.1-beta1(3mo ago)02↓90.9%MITPHPPHP &gt;=8.1

Since Mar 30Pushed 3mo agoCompare

[ Source](https://github.com/saifulferoz/DynamicDbBundle)[ Packagist](https://packagist.org/packages/feroz/dynamic-db-bundle)[ RSS](/packages/feroz-dynamic-db-bundle/feed)WikiDiscussions main Synced 4w ago

READMEChangelog (1)Dependencies (4)Versions (3)Used By (0)

DynamicDbBundle
===============

[](#dynamicdbbundle)

`DynamicDbBundle` is a Symfony bundle that allows you to store database connection configurations in a database table and seamlessly fetch and instantiate connections and entity managers at runtime.

With this bundle, you can natively use `$doctrine->getConnection('dynamic_name')` just like any conventionally configured connection in your `doctrine.yaml`.

---

Features
--------

[](#features)

- **Seamless Doctrine Integration**: Fetches database configuration dynamically via Doctrine's `ManagerRegistry`.
- **On-The-Fly Connections**: Creates connections and entity managers completely dynamically without requiring compile-time setup.
- **Auto Cache Rebuilding**: Automatically handles clearing the Symfony cache when your dynamic database connection entities are created, updated, or removed, ensuring any new connections are immediately discoverable.
- **Runtime Secret Injection**: Allows the consumer application to supply the decryption secret via Symfony's DI container, which is automatically forwarded to the connection entity via `setSecret()` before the connection config is built.

---

Installation
------------

[](#installation)

Add the bundle to your project via Composer (if published):

```
composer require feroz/dynamic-db-bundle
```

Ensure the bundle is registered in your `config/bundles.php`:

```
return [
    // ...
    Feroz\DynamicDbBundle\DynamicDbBundle::class => ['all' => true],
];
```

---

Usage Guide
-----------

[](#usage-guide)

### 1. Create a Configuration Entity

[](#1-create-a-configuration-entity)

Create a standard Doctrine Entity in your application that stores the database connection configurations. **Crucially, this entity must implement `DynamicDbConnectionInterface`** and provide implementations for all interface methods, including `setSecret()`.

The `setSecret()` method is called automatically by `DynamicDbProvider` before building the connection config, allowing your entity to make the secret available to downstream logic (e.g., for custom password decryption).

```
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Feroz\DynamicDbBundle\Contract\DynamicDbConnectionInterface;

#[ORM\Entity]
class TenantConnection implements DynamicDbConnectionInterface
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private ?string $connectionName = null; // e.g., "tenant_1"

    #[ORM\Column(length: 255)]
    private ?string $dbHost = null;

    #[ORM\Column(length: 255)]
    private ?string $dbName = null;

    #[ORM\Column(length: 255)]
    private ?string $dbUser = null;

    #[ORM\Column(length: 255)]
    private ?string $dbPassword = null;

    private ?string $secret = null;

    // --- DynamicDbConnectionInterface implementation ---

    public function getConnectionName(): string { return $this->connectionName; }
    public function getConnectionString(): ?string { return null; } // Optional: Return Oracle TNS string here
    public function getDatabaseDriver(): string { return 'pdo_mysql'; } // Hardcode or map a column
    public function getDatabaseHost(): string { return $this->dbHost; }
    public function getDatabasePort(): int|string { return 3306; }
    public function getDatabaseName(): string { return $this->dbName; }
    public function getDatabaseUser(): string { return $this->dbUser; }
    public function getDatabasePassword(): string { return $this->dbPassword; }

    /**
     * Called automatically by DynamicDbProvider before the connection config is built.
     * The secret is null when none is configured — implement your decryption logic here.
     */
    public function setSecret(?string $secret): void
    {
        $this->secret = $secret;
    }
}
```

### 2. Fetch the Dynamic Connection

[](#2-fetch-the-dynamic-connection)

You can fetch the connection or the manager directly through Symfony's core Doctrine integration! The bundle decorates the Doctrine registry to seamlessly integrate.

```
namespace App\Controller;

use Doctrine\Persistence\ManagerRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class TenantController extends AbstractController
{
    #[Route('/tenant/{tenantName}', name: 'tenant_dashboard')]
    public function index(string $tenantName, ManagerRegistry $doctrine): Response
    {
        // Behind the scenes, the bundle fetches the row matching $tenantName
        // and initializes the connection seamlessly!
        $connection = $doctrine->getConnection($tenantName);

        // Alternatively, grab the dynamic EntityManager
        $entityManager = $doctrine->getManager($tenantName);

        // Run queries for this specific tenant's database
        $results = $connection->executeQuery('SELECT * FROM users')->fetchAllAssociative();

        return $this->json($results);
    }
}
```

### 3. Password Encryption (Consumer Responsibility)

[](#3-password-encryption-consumer-responsibility)

The bundle does **not** provide a built-in encryption utility. Password encryption and decryption are entirely the consumer's responsibility.

The recommended pattern is:

1. **Encrypt** the password before persisting the entity (using any encryption library of your choice).
2. **Decrypt** the password inside `getDatabasePassword()` of your entity, using the secret injected via `setSecret()`.

```
public function setSecret(?string $secret): void
{
    $this->secret = $secret;
}

public function getDatabasePassword(): string
{
    if ($this->secret !== null) {
        // Decrypt using your own logic / library
        return MyEncryptionHelper::decrypt($this->dbPassword, $this->secret);
    }

    return $this->dbPassword; // Return as-is if no secret configured
}
```

### 4. Passing a Secret via Dependency Injection (for Encrypted Passwords)

[](#4-passing-a-secret-via-dependency-injection-for-encrypted-passwords)

`DynamicDbProvider` accepts `$secret` as an **optional constructor parameter**. The recommended approach is to bind it in your application's `services.yaml` using a Symfony parameter (e.g. from an environment variable):

```
# config/services.yaml
parameters:
    dynamic_db_secret: '%env(DYNAMIC_DB_SECRET)%'

services:
    Feroz\DynamicDbBundle\Service\DynamicDbProvider:
        arguments:
            $secret: '%dynamic_db_secret%'
```

With this configuration, `DynamicDbProvider` will automatically call `$entity->setSecret($secret)` on the fetched connection entity before building the connection config, giving the entity access to the secret for custom decryption logic.

If no secret is needed, simply omit the binding — the `$secret` parameter defaults to `null` and `setSecret()` will not be called.

### How it Works

[](#how-it-works)

1. When you call `$doctrine->getConnection('X')`, the wrapped `DynamicRegistryDecorator` intercepts the request.
2. If Doctrine natively doesn't know about connection `X`, `DynamicDbProvider` kicks in.
3. It finds the class implementing `DynamicDbConnectionInterface` dynamically and uses the default EntityManager to fetch the entity matching `connectionName = 'X'`.
4. If a `$secret` was configured (via DI), it calls `$entity->setSecret($secret)` on the fetched entity before building the config.
5. The `DynamicEntityManagerFactory` boots up the new ORM connection using the config.
6. The connection is cached locally for the remainder of the request.

###  Health Score

31

—

LowBetter than 66% of packages

Maintenance82

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity30

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

91d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/42f7ccbb50ac26336f56240519756fffae416abcdc6ff44540947bd2cc941487?d=identicon)[saifulferoz](/maintainers/saifulferoz)

---

Top Contributors

[![saifulferoz](https://avatars.githubusercontent.com/u/15348453?v=4)](https://github.com/saifulferoz "saifulferoz (7 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/feroz-dynamic-db-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/feroz-dynamic-db-bundle/health.svg)](https://phpackages.com/packages/feroz-dynamic-db-bundle)
```

###  Alternatives

[rcsofttech/audit-trail-bundle

Enterprise-grade, high-performance Symfony audit trail bundle. Automatically track Doctrine entity changes with split-phase architecture, multiple transports (HTTP, Queue, Doctrine), and sensitive data masking.

1175.2k](/packages/rcsofttech-audit-trail-bundle)[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k17.5M378](/packages/easycorp-easyadmin-bundle)[kimai/kimai

Kimai - Time Tracking

4.8k8.7k1](/packages/kimai-kimai)[ahmed-bhs/doctrine-doctor

Runtime analysis tool for Doctrine ORM integrated into Symfony Web Profiler. Unlike static linters, it analyzes actual query execution at runtime to detect performance bottlenecks, security vulnerabilities, and best practice violations during development with real execution context and data.

939.0k](/packages/ahmed-bhs-doctrine-doctor)[2lenet/crudit-bundle

The easy like Crud'it Bundle.

1615.6k12](/packages/2lenet-crudit-bundle)[heymoon/doctrine-psql-enum

Store PHP native enums as PostgeSQL custom enum types

256.6k](/packages/heymoon-doctrine-psql-enum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
