Transacciones

Las transacciones garantizan que, o se ejecutan todas las operaciones de la transacción, o no se ejecuta ninguna. Son útiles para asegurar la consistencia de los datos en operaciones complejas.

La forma más sencilla de usar transacciones es esta:

$database->beginTransaction();
try {
	$database->query('DELETE FROM articles WHERE id = ?', $id);
	$database->query('INSERT INTO audit_log', [
		'article_id' => $id,
		'action' => 'delete'
	]);
	$database->commit();
} catch (\Exception $e) {
	$database->rollBack();
	throw $e;
}

El mismo resultado se consigue de forma mucho más elegante con el método transaction(). Acepta un callback que se ejecuta dentro de la transacción. Si el callback se ejecuta sin excepción, la transacción se confirma automáticamente. Si se produce una excepción, la transacción se revierte y la excepción se propaga hacia arriba.

$database->transaction(function ($database) use ($id) {
	$database->query('DELETE FROM articles WHERE id = ?', $id);
	$database->query('INSERT INTO audit_log', [
		'article_id' => $id,
		'action' => 'delete'
	]);
});

Las llamadas a transaction() se pueden anidar, lo que facilita componer métodos que gestionan cada uno su propia transacción. Solo la transacción más externa se envía realmente a la base de datos como BEGIN/COMMIT; las llamadas internas se limitan a llevar la cuenta del nivel de anidamiento. Llamar manualmente a beginTransaction(), commit() o rollBack() dentro de un callback de transaction() lanza una LogicException.

El método transaction() también puede devolver valores:

$count = $database->transaction(function ($database) {
	$result = $database->query('UPDATE users SET active = ?', true);
	return $result->getRowCount(); // devuelve el número de filas actualizadas
});