Skip to content

Connection

Muhammet Şafak edited this page May 24, 2026 · 1 revision

Connection

InitORM\DBAL\Connection\Connection is the single entry point. This page documents the credential keys, lifecycle rules, and configuration tricks in full.

Constructor

public function __construct(
    array $credentials = [],
    ?DataMapperFactoryInterface $dataMapperFactory = null,
    ?DsnBuilder $dsnBuilder = null
);
  • $credentials — associative array; merged on top of the defaults (table below).
  • $dataMapperFactory — optional. Replace with a custom factory when you need to wrap statements differently. See Factories and DI.
  • $dsnBuilder — optional. Replace to support a driver DBAL doesn't know about. See Factories and DI.

Credentials

Key Default Notes
dsn '' If empty, built from driver/host/port/database.
driver 'mysql' mysql, pgsql, sqlite, or anything PDO supports.
host '127.0.0.1'
port 3306 Use 5432 for PostgreSQL.
database '' For SQLite a filesystem path or ':memory:'.
username null
password null
charset 'utf8mb4' MySQL-only SET NAMES. Pass '' to skip.
collation null When set, appended as COLLATE to SET NAMES.
options [] PDO attribute map; merged with library defaults.
queryOptions [] Default PDO prepare options applied to every query.
log null See Logging.
debug false When true, query failure logs include serialised args.
queryLogs false When true, every query is appended to the log buffer.

Default PDO attributes

These are merged with any options you supply (yours take precedence):

Attribute Default value
PDO::ATTR_EMULATE_PREPARES false
PDO::ATTR_PERSISTENT false
PDO::ATTR_ERRMODE PDO::ERRMODE_EXCEPTION
PDO::ATTR_DEFAULT_FETCH_MODE PDO::FETCH_ASSOC

Heads-up. In initorm/dbal 1.x, ATTR_PERSISTENT defaulted to true. That silently shared connections — and therefore transactions and prepared-statement caches — across requests. The 2.x default is false. Opt back in deliberately if you need pool behaviour, and read Transactions first.

Driver examples

MySQL / MariaDB

use InitORM\DBAL\Connection\Connection;

$db = new Connection([
    'driver'    => 'mysql',
    'host'      => 'db',
    'port'      => 3306,
    'database'  => 'shop',
    'username'  => 'app',
    'password'  => getenv('DB_PASS'),
    'charset'   => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
]);

PostgreSQL

$db = new Connection([
    'driver'   => 'pgsql',
    'host'     => 'pg',
    'port'     => 5432,
    'database' => 'shop',
    'username' => 'app',
    'password' => getenv('DB_PASS'),
    'charset'  => '',          // pgsql ignores SET NAMES — leave empty
]);

SQLite — file

$db = new Connection([
    'driver'   => 'sqlite',
    'database' => __DIR__ . '/storage/app.sqlite',
    'charset'  => '',
]);

SQLite — in-memory (great for tests)

$db = new Connection([
    'driver'   => 'sqlite',
    'database' => ':memory:',
    'charset'  => '',
]);

Custom / unknown driver

If you pass a driver DBAL does not know about, the DSN builder falls back to the MySQL-shaped DSN template (driver:host=…;port=…;dbname=…;charset=…). For anything outside that shape, pass a complete dsn yourself:

$db = new Connection([
    'driver' => 'oci',
    'dsn'    => 'oci:dbname=//host:1521/XE;charset=AL32UTF8',
]);

…or supply a custom DsnBuilder (see Factories and DI).

Lifecycle

$db = new Connection([...]);   // no PDO yet
$db->getPDO();                  // PDO opens here
$db->query('SELECT 1');         // re-uses the same PDO
$db->disconnect();              // drops the in-process reference

Lazy connect

The PDO instance is created on first need. This means:

  • A Connection is essentially free to construct.
  • A misconfigured connection only surfaces the error when you actually try to query.

Setters guard against mutation after connect

Once PDO exists, calling setHost(), setDatabase(), setCharset(), setDriver(), setOptions(), setDsn(), setPort(), setUsername(), or setPassword() raises ConnectionAlreadyEstablishedException. To change credentials, call disconnect() first or clone() a fresh instance:

use InitORM\DBAL\Connection\Exceptions\ConnectionAlreadyEstablishedException;

$db->getPDO();
try {
    $db->setDatabase('other');
} catch (ConnectionAlreadyEstablishedException $e) {
    $db->disconnect();
    $db->setDatabase('other');
    $db->getPDO();
}

The historical name ValidConnectionAvailableException is the parent class of ConnectionAlreadyEstablishedException, so 1.x catch blocks keep working.

disconnect() is best-effort

disconnect() sets the internal PDO reference to null and returns true. With PDO::ATTR_PERSISTENT => true, PHP returns the connection to the pool rather than closing it. There is no portable way to force- close a persistent connection.

Cloning

clone() returns a fresh, disconnected Connection carrying the same credentials. Use it when you need a sibling connection (a second cursor, a parallel transaction, a separate database) without re-wiring config:

$replica = $primary->clone()->setHost('replica.internal');

The replica has its own credentials map and its own PDO instance. The factories (DataMapperFactory, DsnBuilder) are shared by reference.

Identifier safety

setCharset(), setDriver(), and the internal MySQL SET NAMES step all reject any value that does not match [A-Za-z0-9_]+. Charset and collation values cannot be parameterised in SQL, so the regex acts as defence-in-depth against accidental injection through configuration.

Bad input throws ConnectionInvalidArgumentException:

use InitORM\DBAL\Connection\Exceptions\ConnectionInvalidArgumentException;

try {
    $db->setCharset("utf8mb4'; DROP TABLE users; --");
} catch (ConnectionInvalidArgumentException $e) {
    // ...
}

Forwarding to PDO

Any method you call on Connection that isn't defined explicitly is forwarded to the underlying PDO instance, with one rewrite: when PDO returns itself (chainable methods), the Connection wrapper is returned instead, so fluent chains span the wrapper boundary.

$db->beginTransaction();
$db->lastInsertId();
$db->quote("O'Reilly");
$db->inTransaction();

If you need the raw PDO, ask for it:

$pdo = $db->getPDO();

What's next

Clone this wiki locally