dongxi7722 2015-08-11 20:22 采纳率: 0%
浏览 67
已采纳

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

I have here a code to insert the order of the customer in the orders table and insert the purchased products in that order in the purchased_products table. I want to check if the insertions were made, otherwise undo the changes with PDO rollback(). My code is:

$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();

Is this way safe? I use a transaction to lock the tables and lastInsertId () to assign the ID of the order to the products that belongs to it. I check the insertions and if something went wrong undo the changes with rollback(). Is my checkout system well prepared and totally safe?

  • 写回答

1条回答 默认 最新

  • doulu3808 2015-08-11 23:32
    关注

    It makes more sence to do all your inserts inside the same Try/Catch and then if the order insert or the order_item insert fails a single catch block will deal with the rollback and any cleanup/reporting that may be required.

    The way you had it the order insert could fail and then the order_item insert would still try and run, possibly creating items without a owning order.

    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;
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 关于#hadoop#的问题
  • ¥15 (标签-Python|关键词-socket)
  • ¥15 keil里为什么main.c定义的函数在it.c调用不了
  • ¥50 切换TabTip键盘的输入法
  • ¥15 可否在不同线程中调用封装数据库操作的类
  • ¥15 微带串馈天线阵列每个阵元宽度计算
  • ¥15 keil的map文件中Image component sizes各项意思
  • ¥20 求个正点原子stm32f407开发版的贪吃蛇游戏
  • ¥15 划分vlan后,链路不通了?
  • ¥20 求各位懂行的人,注册表能不能看到usb使用得具体信息,干了什么,传输了什么数据