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.