Connection
Тонкая PDO-обёртка с удобными методами, транзакциями и поддержкой savepoints.
Содержание
Создание подключения
Из DSN-параметров
use AsceticSoft\Rowcast\Connection;
$connection = Connection::create(
dsn: 'mysql:host=localhost;dbname=app',
username: 'root',
password: 'secret',
);
Из существующего PDO-экземпляра
$pdo = new \PDO('sqlite::memory:');
$connection = new Connection($pdo);
Connection автоматически устанавливает PDO::ATTR_ERRMODE в PDO::ERRMODE_EXCEPTION, чтобы все ошибки базы данных выбрасывали исключения.
Выполнение прямых запросов
executeQuery — SELECT-запросы
Возвращает PDOStatement для чтения результатов:
$stmt = $connection->executeQuery('SELECT * FROM users WHERE id = ?', [1]);
executeStatement — INSERT/UPDATE/DELETE
Возвращает количество затронутых строк:
$affected = $connection->executeStatement(
'UPDATE users SET name = ? WHERE id = ?',
['Alice', 1],
);
Вспомогательные методы выборки
// Получить все строки как ассоциативные массивы
$rows = $connection->fetchAllAssociative('SELECT * FROM users');
// Получить одну строку
$row = $connection->fetchAssociative('SELECT * FROM users WHERE id = ?', [1]);
// Получить скалярное значение
$count = $connection->fetchOne('SELECT COUNT(*) FROM users');
Транзакции
Ручное управление транзакциями
$connection->beginTransaction();
try {
$connection->executeStatement('INSERT INTO users (name) VALUES (?)', ['Alice']);
$connection->executeStatement('INSERT INTO users (name) VALUES (?)', ['Bob']);
$connection->commit();
} catch (\Throwable $e) {
$connection->rollBack();
throw $e;
}
Автоматические транзакции (рекомендуется)
$connection->transactional(function (Connection $conn) {
$conn->executeStatement('INSERT INTO users (name) VALUES (?)', ['Alice']);
$conn->executeStatement('INSERT INTO users (name) VALUES (?)', ['Bob']);
});
Метод transactional() автоматически коммитит при успехе и откатывает при исключении.
Вложенные транзакции (Savepoints)
По умолчанию вызов beginTransaction() внутри активной транзакции завершится ошибкой. Включите вложенность на основе savepoints:
// Через фабрику
$connection = Connection::create(
'mysql:host=localhost;dbname=app', 'root', 'secret',
nestTransactions: true,
);
// Через конструктор
$connection = new Connection($pdo, nestTransactions: true);
При включении внутренние вызовы beginTransaction() создают SQL SAVEPOINT, а commit() / rollBack() освобождают или откатывают соответствующий savepoint:
$connection->transactional(function (Connection $conn) {
$conn->executeStatement('INSERT INTO users (name) VALUES (?)', ['Alice']);
try {
$conn->transactional(function (Connection $inner) {
$inner->executeStatement('INSERT INTO users (name) VALUES (?)', ['Bob']);
throw new \RuntimeException('внутренняя ошибка');
});
} catch (\RuntimeException) {
// Откатывается только внутренняя транзакция (Bob).
// Вставка Alice сохраняется.
}
});
// Alice закоммичена; Bob — нет.
Проверка уровня вложенности
$level = $connection->getTransactionNestingLevel();
// 0 — нет активной транзакции
Построитель запросов
Создание fluent-построителя запросов из подключения:
$qb = $connection->createQueryBuilder();
$rows = $qb->select('id', 'name')
->from('users')
->where('status = :status')
->setParameter('status', 'active')
->fetchAllAssociative();
Подробнее см. на странице Построитель запросов.
Доступ к PDO
$pdo = $connection->getPdo();
Используйте прямой доступ к PDO с осторожностью. Предпочтительно использовать методы Connection для поддержания согласованной обработки ошибок и управления транзакциями.