在本指南中,我们将向您展示如何将事务与 PHP 的 PDO 对象一起使用。
对于那些不知道的人,数据库事务代表一个“块”或一个“单元”工作。
在大多数情况下,这个工作“单元”将由多个查询组成,这些查询以某种方式相互关联。
在某些情况下,您可能希望确保在将更改提交到数据库之前成功执行所有查询。
对于这个例子,我们将创建一个模拟 PHP 应用程序,为用户帐户添加资金。
在这种情况下,我们有两个查询。第一个将支付记录插入一个名为“payments”的表中。第二个将更新用户帐户的余额。
- /**
- * Connect to MySQL and instantiate the PDO object.
- * Set the error mode to throw exceptions and disable emulated prepared statements.
- */
- $pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '', array(
- PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
- PDO::ATTR_EMULATE_PREPARES => false
- ));
-
-
- //We are going to assume that the user with ID #1 has paid 10.50.
- $userId = 1;
- $paymentAmount = 10.50;
-
-
- //We will need to wrap our queries inside a TRY / CATCH block.
- //That way, we can rollback the transaction if a query fails and a PDO exception occurs.
- try{
-
- //We start our transaction.
- $pdo->beginTransaction();
-
-
- //Query 1: Attempt to insert the payment record into our database.
- $sql = "INSERT INTO payments (user_id, amount) VALUES (?, ?)";
- $stmt = $pdo->prepare($sql);
- $stmt->execute(array(
- $userId,
- $paymentAmount,
- )
- );
-
- //Query 2: Attempt to update the user's profile.
- $sql = "UPDATE users SET credit = credit + ? WHERE id = ?";
- $stmt = $pdo->prepare($sql);
- $stmt->execute(array(
- $paymentAmount,
- $userId
- )
- );
-
- //We've got this far without an exception, so commit the changes.
- $pdo->commit();
-
- }
- //Our catch block will handle any exceptions that are thrown.
- catch(Exception $e){
- //An exception has occured, which means that one of our database queries
- //failed.
- //Print out the error message.
- echo $e->getMessage();
- //Rollback the transaction.
- $pdo->rollBack();
- }
在此示例中,我们确保在提交更改之前所有查询都成功。
换句话说,如果第二个查询无法更新用户的信用余额,我们不想在支付表中插入记录。
上面的PHP代码的一步一步的解释:
如果我们的查询之一失败,则会抛出 PDO 异常。
如果发生这种情况,我们的 catch 块内的代码将执行。
在那个阶段,MySQL 将中止事务并回滚任何更改。
一些关键术语的快速解释。