使用PDO检查数据库插入和回滚的正确方法

时间:2015-08-11 20:22:45

标签: php mysql pdo

我这里有一个代码,用于在orders表中插入客户的订单,并在purchased_products表中按顺序插入购买的产品。我想检查是否进行了插入,否则使用PDO rollback()撤消更改。我的代码是:

$options = [
PDO::ATTR_ERRMODE          => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false
];    

try
{
    $connection = new PDO("mysql:host={$HOST};dbname={$DB_NAME}", $USERNAME, $PASS, $options);
}

$connection->beginTransaction();

try
{
    $sql = "INSERT INTO orders (customer_id, customer_name, order_value, order_date)
            VALUES (?, ?, ?, ?)";

    $query = $connection->prepare($sql);
    $query->execute(array
    (
        $user_id,
        $user['user_name'],
        $order_value,
        $date
    ));

    $id_of_respective_order = $connection->lastInsertId();
}
catch(PDOException $exception) 
{
    $connection->rollback();
    echo "<script>alert('An error occurred while completing your purchase. Please try again later.');</script>";
}

try
{
    $sql = "INSERT INTO purchased_products (order_id, product_name, product_price, quantity)
            VALUES (?, ?, ?, ?)";

    $query = $connection->prepare($sql);

    foreach($_SESSION['cart'] as $product)
    {
        $query->execute(array
        (
            $id_of_respective_order,
            $product['product_name'],
            $product['product_price'],
            $product['quantity']
        ));
    }
}
catch(PDOException $exception) 
{
    $connection->rollback();
    echo "<script>alert('An error occurred while completing your purchase. Please try again later.');</script>";
}

$connection->commit();

这样安全吗?我使用事务来锁定表,并lastInsertId ()将订单的ID分配给属于它的产品。我检查了插入内容,如果出现问题,请使用rollback()撤消更改。我的结账系统是否准备充分且完全安全?

1 个答案:

答案 0 :(得分:0)

在同一个Try / Catch中执行所有插入操作会更加明显,如果订单插入或order_item插入失败,单个catch块将处理回滚以及可能需要的任何清理/报告。

订单插入的方式可能会失败,然后order_item插入仍然会尝试并运行,可能会创建没有拥有订单的项目。

try {
    $connection = new PDO("mysql:host={$HOST};dbname={$DB_NAME}", 
                          $USERNAME, $PASS);
    $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e ) {
    echo 'Connection failed: ' . $e->getMessage();
    exit;
}

$connection->beginTransaction();

try {
    $sql = "INSERT INTO orders 
           (customer_id, customer_name, order_value, order_date)
           VALUES (?, ?, ?, ?)";

    $query = $connection->prepare($sql);
    $query->execute(array( $user_id,
                         $user['user_name'],
                         $order_value,
                         $date
                        )
                   );

    $id_of_respective_order = $connection->lastInsertId();

    $sql = "INSERT INTO purchased_products 
                   (order_id, product_name, product_price, quantity)
            VALUES (?, ?, ?, ?)";

    $query = $connection->prepare($sql);

    foreach($_SESSION['cart'] as $product) {
        $query->execute(array( $id_of_respective_order,
                               $product['product_name'],
                               $product['product_price'],
                               $product['quantity']
                              )
                       );
    }

    $connection->commit();

}
catch(PDOException $e) {
    $connection->rollBack();

    echo 'Order creation failed: ' . $e->getMessage();
    echo "<script>alert('An error occurred while completing your purchase. Please try again later.');</script>";
    exit;
}