Skip to main content

Factory and manager

The factory builds a connection from a config. The manager decides which config that is and remembers the result.

The factory

ConnectionFactory is constructed with the drivers it may use and, optionally, the middleware that wraps everything it creates.

use Dirthara\Database\Connection\ConnectionFactory;

$factory = new ConnectionFactory($drivers, $middleware);

$connection = $factory->create($config);

Both arguments are iterable, so a generator or a lazy service-container collection works as well as an array.

Drivers are keyed by their DriverName. Registering the same driver name twice throws a ConnectionException at construction rather than letting one registration silently shadow the other. Asking for a config whose driver was never registered throws a ConnectionException from create().

create() returns a fresh Connection on every call. Caching is the manager's job.

The manager

ConnectionManager holds the configs, resolves one by name, and caches the connection it produced.

use Dirthara\Database\Connection\ConnectionManager;

$manager = new ConnectionManager($factory, $configs, default: 'primary');
ArgumentTypeDefaultMeaning
factoryConnectionFactoryrequiredBuilds a connection from a config.
configsiterable<ConnectionConfig>requiredThe configured connections, keyed internally by their name.
defaultstring'default'The name used when a connection is requested without one.

Configuring the same connection name twice throws a ConnectionException at construction. The default name is not checked at construction; asking for a connection that was never configured throws from connection(), with the names that are configured in its context.

Methods

$manager->connection(); // the default connection
$manager->connection('reporting'); // a connection by name

$manager->names(); // ['primary', 'reporting']

$manager->disconnect('reporting');
$manager->disconnectAll();
MethodBehaviour
connection(?string $name = null)Returns the named connection, building it on first request and returning the same instance afterwards. Falls back to the default name. Throws ConnectionException when the name is not configured.
disconnect(?string $name = null)Closes the connection and drops it from the cache, so the next request builds a new one. A no-op when that connection was never built.
disconnectAll()Disconnects every connection that has been built.
names()The configured connection names, in the order they were registered.

Disconnecting throws a TransactionException when a transaction is still active on that connection, rather than dropping the handle and losing the uncommitted work.

Laziness

Two things are deferred, and they are worth keeping apart.

The manager defers building a connection: connection('reporting') is the first time ConnectionFactory::create() runs for that name. The connection defers opening it: PDO is constructed on the first execute(), lastInsertId(), or transaction operation.

$connection = $manager->connection('reporting'); // no socket yet
$connection->transactions(); // still no socket
$connection->execute('SELECT 1'); // now it connects

So a config for a database this request never touches costs nothing, and a misconfigured host is not an error until something needs it. Registering ten connections in a container is fine.

Using one connection

The manager exists for applications with more than one database. With a single connection, the factory is enough:

$connection = $factory->create($config);

You give up the caching and the disconnect bookkeeping, so hold on to the returned instance rather than calling create() per query — each call builds a connection that opens its own PDO handle.