Multiple DBAL connections in Symfony 4

The documentation is pretty helpful about how to use multiple connections
with the Doctrine bundle. However after switching over from Silex you may want to use DBAL without the bundle. This article shows a couple of ways to configure connections and how to inject them with DBAL.

In order to create a connection use the getConnection factory method. Wire this up in config/services.yaml like so:

# config/services.yaml
# ...
Doctrine\DBAL\Connection:
factory: Doctrine\DBAL\DriverManager::getConnection
arguments:
$params:
driver: pdo_mysql
url: '%env(DATABASE_URL)%'
charset: UTF8

If you prefer to set each param individually it looks something like this:

# config/services.yaml
# ...

Doctrine\DBAL\Connection:
factory: Doctrine\DBAL\DriverManager::getConnection
arguments:
$params:
driver: pdo_mysql
host: '%env(DATABASE_HOST)%'
port: ~
user: '%env(DATABASE_USER)%'
password: '%env(DATABASE_PASSWORD)%'
dbname: '%env(DATABASE_SCHEMA)%'
charset: UTF8

In order to have multiple connections you need to set up multiple services:

# config/services.yaml
# ...
Doctrine\DBAL\Connection:
factory: Doctrine\DBAL\DriverManager::getConnection
arguments:
$params:
driver: pdo_mysql
url: '%env(DATABASE_URL)%'
charset: UTF8
db.statistics:
class: Doctrine\DBAL\Connection
factory: Doctrine\DBAL\DriverManager::getConnection
arguments:
$params:
driver: pdo_mysql
url: '%env(DATABASE_URL_STATISTICS)%'
charset: UTF8

Now that the multiple services are configured they should be wired in to the classes. A basic service like this:

<?php

namespace
App\Service;

use Doctrine\DBAL\Connection;

class DefaultService
{
public function __construct(
Connection $db,
Connection $statistics
) {
//...
}
}

Can be wired like so:

# config/services.yaml
# ...
App\Service\DefaultService:
arguments:
$statistics: '@db.statistics'

This only wires the $statistics param and leaves the $db param to use the default. They can both configured if needed. If you prefer the arguments can be bound by name as well.

The services can also be injected in to controllers but it appears to break some of the method param injections. Binding on the constructor would work like this:

#services.yml
# ...
App\Controller\DefaultController:
public: true
bind:
$places: '@db.places'
$statistics: '@db.statistics'

Like what you read? Give Peter Lafferty a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.