PHP PDO::commit 方法
最后修改于 2025 年 4 月 19 日
PHP 中的 PDO::commit 方法用于最终确定一个事务,使所有更改在数据库中永久生效。它与 PDO 的事务功能一起使用。
基本定义
PDO::commit 提交当前事务。它使得自事务开始以来所做的所有更改永久生效。该方法在成功时返回 true。
语法:public PDO::commit(): bool。如果当前没有活动事务或提交失败,它将抛出 PDOException。
简单的事务提交示例
这展示了一个基本的事务提交。
<?php
declare(strict_types=1);
try {
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->beginTransaction();
$pdo->exec("INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')");
$pdo->commit();
echo "Transaction committed successfully";
} catch (PDOException $e) {
$pdo->rollBack();
echo "Error: " . $e->getMessage();
}
这会启动一个事务,插入一条记录,然后提交它。如果发生任何错误,事务将被回滚。提交操作会使插入永久生效。
事务中的多个操作
这演示了将多个操作作为一个事务进行提交。
<?php
declare(strict_types=1);
try {
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->beginTransaction();
$pdo->exec("UPDATE products SET stock = stock - 5 WHERE id = 101");
$pdo->exec("INSERT INTO orders (product_id, quantity) VALUES (101, 5)");
$pdo->commit();
echo "Order processed successfully";
} catch (PDOException $e) {
$pdo->rollBack();
echo "Order failed: " . $e->getMessage();
}
这在一个事务中更新产品库存并创建一个订单。这两个操作一起成功或一起失败。提交操作会应用这两个更改。
使用预处理语句提交
这展示了使用预处理语句提交事务。
<?php
declare(strict_types=1);
try {
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->beginTransaction();
$stmt = $pdo->prepare("INSERT INTO logs (message, created_at) VALUES (?, NOW())");
$stmt->execute(['System started']);
$stmt->execute(['User logged in']);
$pdo->commit();
echo "Log entries committed";
} catch (PDOException $e) {
$pdo->rollBack();
echo "Logging failed: " . $e->getMessage();
}
这使用预处理语句在事务中插入多个日志条目。提交确保所有插入一起保存。预处理语句更安全。
条件提交
这演示了仅在满足特定条件时才提交。
<?php
declare(strict_types=1);
try {
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->beginTransaction();
$stmt = $pdo->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?");
$stmt->execute([100, 1]);
$balance = $pdo->query("SELECT balance FROM accounts WHERE id = 1")->fetchColumn();
if ($balance >= 0) {
$pdo->commit();
echo "Transaction committed";
} else {
$pdo->rollBack();
echo "Insufficient funds - transaction rolled back";
}
} catch (PDOException $e) {
$pdo->rollBack();
echo "Error: " . $e->getMessage();
}
这会在提交前检查账户余额。只有当余额保持为正时,事务才会提交。否则,它将回滚更改。
带提交的嵌套事务
这展示了 PDO 如何处理嵌套事务(模拟的)。
<?php
declare(strict_types=1);
try {
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->beginTransaction(); // Outer transaction
$pdo->exec("INSERT INTO events (name) VALUES ('Process started')");
try {
$pdo->beginTransaction(); // Inner transaction
$pdo->exec("UPDATE counters SET value = value + 1 WHERE name = 'events'");
$pdo->commit(); // Commits inner transaction
} catch (Exception $e) {
$pdo->rollBack(); // Rolls back inner transaction
throw $e;
}
$pdo->commit(); // Commits outer transaction
echo "All transactions committed";
} catch (PDOException $e) {
$pdo->rollBack(); // Rolls back outer transaction
echo "Error: " . $e->getMessage();
}
PDO 不支持真正的嵌套事务,但会模拟它们。每次提交都对应于其 `beginTransaction`。外部提交使所有更改永久生效。
带错误处理的提交
这演示了提交操作周围的正确错误处理。
<?php
declare(strict_types=1);
$pdo = null;
try {
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->beginTransaction();
$pdo->exec("DELETE FROM temp_data WHERE created_at < DATE_SUB(NOW(), INTERVAL 1 DAY)");
if (!$pdo->commit()) {
throw new Exception("Commit failed");
}
echo "Old data cleaned successfully";
} catch (PDOException $e) {
if ($pdo && $pdo->inTransaction()) {
$pdo->rollBack();
}
echo "Database error: " . $e->getMessage();
} catch (Exception $e) {
if ($pdo && $pdo->inTransaction()) {
$pdo->rollBack();
}
echo "Error: " . $e->getMessage();
}
这展示了围绕提交的健壮错误处理。它会检查提交的返回值,并确保在所有错误情况下都进行回滚。`inTransaction` 检查可防止错误。
数据库类中的提交
这演示了在数据库包装器类中使用 `commit`。
<?php
declare(strict_types=1);
class Database {
private PDO $pdo;
public function __construct(string $dsn, string $user, string $pass) {
$this->pdo = new PDO($dsn, $user, $pass);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
public function transferFunds(int $from, int $to, float $amount): bool {
try {
$this->pdo->beginTransaction();
$stmt = $this->pdo->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?");
$stmt->execute([$amount, $from]);
$stmt = $this->pdo->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?");
$stmt->execute([$amount, $to]);
$this->pdo->commit();
return true;
} catch (PDOException $e) {
$this->pdo->rollBack();
return false;
}
}
}
$db = new Database('mysql:host=localhost;dbname=testdb', 'user', 'password');
if ($db->transferFunds(1, 2, 50.00)) {
echo "Funds transferred successfully";
} else {
echo "Transfer failed";
}
这将在类方法中封装事务处理。只有在两个更新都成功时才提交。该方法返回一个布尔值表示成功。
最佳实践
- 始终检查返回值:提交可能静默失败。
- 使用 try-catch:处理潜在的 PDOException。
- 保持事务简短:最大限度地减少锁定时间。
- 验证 inTransaction:在提交或回滚之前。
- 测试错误场景:确保正确的回滚行为。
来源
本教程介绍了 PDO::commit 方法,并通过实际示例展示了不同场景下的事务处理。
作者
列出 所有 PHP PDO 函数。