トランザクション

トランザクションは、その中のすべての操作が実行されるか、まったく実行されないかのどちらかであることを保証します。込み入った操作でデータの整合性を守るのに役立ちます。

トランザクションのもっとも単純な使い方は次のようになります。

$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;
}

同じことを transaction() メソッドでずっと優雅にできます。これはトランザクションの中で実行されるコールバックを受け取ります。コールバックが例外を投げずに終われば、トランザクションは自動的にコミットされます。例外が起きればトランザクションはロールバックされ、例外はさらに上へ伝わります。

$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'
	]);
});

transaction() の呼び出しは入れ子にできるので、それぞれが自分のトランザクションを管理するメソッドを簡単に組み合わせられます。実際に BEGIN/COMMIT としてデータベースに送られるのは、いちばん外側のトランザクションだけで、内側の呼び出しは入れ子の深さを数えるだけです。transaction() のコールバックの中で beginTransaction()commit()rollBack() を手で呼ぶと LogicException が投げられます。

transaction() メソッドは値を返すこともできます。

$count = $database->transaction(function ($database) {
	$result = $database->query('UPDATE users SET active = ?', true);
	return $result->getRowCount(); // 更新された行の数を返します
});
バージョン: 4.x