⚡️ Connection
Note: While Connection
are part of the Hector ORM ecosystem, they are available as a standalone package:
hectororm/connection
.
You can find it on
Packagist.
You can use them independently of the ORM, in any PHP application. 🎉
The hectororm/connection
package provides a lightweight and highly flexible abstraction layer for managing PDO-based
database connections in PHP. It enables clean handling of basic SQL execution, read/write DSN separation, transactions,
and driver introspection, making it suitable for both simple scripts and advanced web applications.
This guide covers how to create and configure connections, run queries, manage transactions, use multiple connections, introspect driver capabilities, and enable query logging for development and debugging purposes. 🧰
🧱 Creating a Connection
The Connection
class allows you to establish a connection using a DSN (Data Source Name). You can optionally provide
credentials, define a connection name, set up a read-only replica, or inject a logger instance.
🏗️ Constructor Parameters
Parameter | Type | Default | Description |
---|---|---|---|
dsn |
string |
— | DSN string for write operations (required) |
username |
string |
null |
Optional database username |
password |
string |
null |
Optional database password |
readDsn |
string |
null |
Optional DSN string for read operations |
name |
string |
Connection::DEFAULT_NAME |
Optional connection name |
logger |
Logger |
null |
Optional logger instance to capture executed queries |
🔌 Simple Connection
use Hector\Connection\Connection;
$connection = new Connection('mysql:host=localhost;dbname=mydb;user=root;password=secret');
You may also pass credentials explicitly as constructor arguments:
$connection = new Connection(
dsn: 'mysql:host=localhost;dbname=mydb',
username: 'root',
password: 'secret'
);
🐳 Using Secrets in Container Environments
$dsn = 'mysql:host=db;dbname=app';
$username = trim(file_get_contents('/run/secrets/db_user'));
$password = trim(file_get_contents('/run/secrets/db_pass'));
$connection = new Connection(
dsn: $dsn,
username: $username,
password: $password
);
🧭 Read/Write Separation
$connection = new Connection(
dsn: 'mysql:host=master.db;dbname=mydb;user=write_user;password=secret',
readDsn: 'mysql:host=replica.db;dbname=mydb;user=read_user;password=secret'
);
Read operations will use the read DSN until a write or transaction begins, after which the write DSN is used exclusively.
🔎 Executing Queries
The Connection
class provides simple and expressive methods for executing SQL queries and retrieving data.
Query Methods
Method | Description |
---|---|
execute(string $sql, array $params = []) |
Execute a write query (e.g. INSERT , UPDATE ) |
fetchOne(string $sql, array $params = []) |
Fetch a single row (or null if none found) |
fetchAll(string $sql, array $params = []) |
Return a generator of all result rows |
fetchColumn(string $sql, array $params = [], int $column = 0) |
Generator over a single column from result set |
yieldAll(string $sql, array $params = []) |
Alias of fetchAll(...) using a generator |
yieldColumn(string $sql, array $params = [], int $column = 0) |
Alias of fetchColumn(...) using a generator |
Usage Example
$affected = $connection->execute(
'UPDATE users SET name = ? WHERE id = ?',
['Alice', 1]
);
$user = $connection->fetchOne('SELECT * FROM users WHERE id = ?', [1]);
foreach ($connection->fetchAll('SELECT * FROM users') as $row) {
// Process each row
}
foreach ($connection->fetchColumn('SELECT email FROM users') as $email) {
// Process each email address
}
🆔 Last Insert ID
$connection->execute('INSERT INTO posts (title) VALUES (?)', ['Hello']);
$id = $connection->getLastInsertId();
🔁 Transactions
Ensure atomic operations using transactions.
Usage Example
$connection->beginTransaction();
try {
$connection->execute('INSERT INTO users (name) VALUES (?)', ['Bob']);
$connection->execute('INSERT INTO profiles (user_id) VALUES (?)', [$connection->getLastInsertId()]);
$connection->commit();
} catch (\Throwable $e) {
$connection->rollBack();
throw $e;
}
Transaction API
Method | Description |
---|---|
beginTransaction() |
Start a new transaction |
commit() |
Commit the current transaction |
rollBack() |
Roll back the current transaction |
inTransaction() |
Returns true if inside a transaction |
⚠️ Note: Nested calls to
beginTransaction()
are ignored. Each transaction must be matched with acommit()
orrollBack()
.
🧩 Managing Multiple Connections
Use the ConnectionSet
class to register and retrieve multiple named Connection
instances.
ConnectionSet API
Method | Description |
---|---|
addConnection(Connection) |
Register a Connection instance |
hasConnection(string) |
Check if a connection with the given name exists |
getConnection(string $name = DEFAULT) |
Retrieve a named connection or the default one |
Usage Example
use Hector\Connection\Connection;
use Hector\Connection\ConnectionSet;
$set = new ConnectionSet();
$set->addConnection(new Connection('mysql:host=localhost;dbname=app', name: 'main'));
$set->addConnection(new Connection('mysql:host=replica;dbname=app', name: 'replica'));
$main = $set->getConnection();
$replica = $set->getConnection('replica');
🪵 Query Logging
To help debug and optimize queries, you can enable logging using the built-in Logger
class. This logger collects
detailed information for each executed SQL statement, including execution time and stack trace.
⚠️ Logging should be disabled in production environments to avoid performance penalties and potential data exposure.
Logger API
Class | Method | Description |
---|---|---|
Logger |
getLogs(): LogEntry[] |
Retrieve captured query logs |
LogEntry |
getStatement(): string |
Executed SQL query |
getParameters(): array |
Parameters bound to the query | |
getDuration(): float |
Execution time in milliseconds | |
getTrace(): array |
PHP stack trace of query execution |
Usage Example
use Hector\Connection\Log\Logger;
$logger = new Logger();
$connection = new Connection('mysql:host=localhost;dbname=app', logger: $logger);
$connection->fetchOne('SELECT * FROM users WHERE id = ?', [1]);
foreach ($logger->getLogs() as $log) {
echo $log->getStatement();
print_r($log->getParameters());
echo $log->getDuration() . "ms\n";
}
🔍 Driver Information
The Connection
class can return introspective metadata about the current PDO driver in use.
DriverInfo API
Method | Description |
---|---|
getDriver(): string |
Name of the underlying PDO driver |
getVersion(): string |
Version string of the driver |
getCapabilities() |
Returns DriverCapabilities object |
DriverCapabilities API
Method | Description |
---|---|
hasLock(): bool |
Whether SQL FOR UPDATE is supported |
hasLockAndSkip(): bool |
Whether SKIP LOCKED is supported |
hasWindowFunctions(): bool |
Whether SQL window functions are supported |
hasJson(): bool |
Whether native JSON functions are supported |
hasStrictMode(): bool |
Whether strict SQL mode is enforced |