将订单ID与属于它的产品相关联的最佳方式

时间:2015-05-06 02:19:20

标签: php sql pdo


我正在开发一个商店系统,我使用我能找到的唯一方法将订单的ID与属于它的产品联系起来。
当有人购买东西时,首先将订单添加到表orders中,并附上他们的详细信息,包括该订单的ID(order_id),由SQL自动递增。
我使用这是为了向表orders添加订单:

INSERT INTO orders SET customer_id = '{$customer_id}', customer_name = '{$user['customer_name']}', order_price = '{$total_price}', order_date = '{$date}'"

好的,订单已添加。现在,按顺序,属于该订单的产品将被添加到另一个表格purchased_products
我使用PDO lastInsertId()从最后插入的order_id表格orders然后在另一个名为Foreign Key的表格中添加该订单的每个产品order_id purchased_products。为此,我使用:

$respective_order_id = $connection->lastInsertId();

foreach($_SESSION['cart'] as $product)
{
    $sql = "INSERT INTO purchased_products SET order_id = '{$respective_order_id}', product_name = '{$product['product_name']}', product_price = '{$product['product_price']}', quantity = '{$product['quantity']}'";
}

这些代码同时运行。首先,订单将添加到orders表中,其order_id自动递增,然后该订单的所有产品也将添加到purchased_products表和{{1}其中每一个的Foreign Key将具有order_id表中插入的最后order_id的值。稍后我会通过咨询外键orders来显示产品的任何订单。
到目前为止,它运作良好。正如我所说的,这是我找到的唯一方法,即使用属于它的产品分配订单的ID。我的问题是:这是安全的吗?如果几个人同时购买怎么样?是否存在交换ID或未添加/或订单错误的风险?如果有经验的人回答这些问题,我会非常感激,因为这让我害怕,我想知道我是否可以相信这种方法。

修改
更多细节!
我的数据库连接:

order_id

我用来在两个表中插入数据的所有代码:

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

catch(PDOException $exception)
{
    echo "Connection error: " . $exception->getMessage();
}

编辑2更新
有些产品可能有额外的阵列(即颜色),有些则没有。但是默认情况下所有数组都填充了这些数组:$sql = "INSERT INTO orders SET customer_id = '{$customer_id}', customer_name = '{$user['customer_name']}', order_price = '{$total_price}', order_date = '{$date}'" $query = $connection->prepare($sql); $query->execute(); $respective_order_id = $connection->lastInsertId(); foreach($_SESSION['cart'] as $product) { $sql = "INSERT INTO purchased_products SET order_id = '{$respective_order_id}', product_name = '{$product['product_name']}', product_price = '{$product['product_price']}', quantity = '{$product['quantity']}'"; $query = $connection->prepare($sql); $query->execute(); } product_nameproduct_price。我已经调整了我的逻辑,使用<提供的代码检查额外的参数强> peterm :

product_quantity

如果SESSION中的额外参数数组不为null,则SQL表中的$connection->beginTransaction(); $sql = "INSERT INTO orders (customer_id, customer_name, order_price, order_date) VALUES (?,?,?,?)"; $query = $connection->prepare($sql); $query->execute(array ( $customer_id, $user['customer_name'], $total_price, $date )); $respective_order_id = $connection->lastInsertId(); $sql = "INSERT INTO purchased_products (order_id, product_name, product_price, quantity, colour) VALUES (?,?,?,?,?)"; $query = $connection->prepare($sql); foreach($_SESSION['cart'] as $product) { $additional_param = array ( 'colour' => NULL ); $colour = array_filter($product['colour']); if(!empty($colour)) { $additional_param['colour'] = $product['colour']['colour_name']; } $query->execute(array ( $respective_order_id, $product['product_name'], $product['product_price'], $product['quantity'], $additional_param['colour'] )); } $connection->commit(); 键将填充产品颜色。否则,它将填充SQL colour

1 个答案:

答案 0 :(得分:2)

  1. 使用PDO的lastInsertId(),取决于驱动程序,但只要您使用正确的自动递增类型的对象(即MySQL中的AUTO_INCREMENT或PostgreSQL中的序列),就可以安全使用。 MySQL驱动程序使用了LAST_INSERT_ID()

  2. 如果您关心事务完整性,请考虑将整个操作包装到事务中。这样,它可以全部正确提交或回滚。没有孤立的订单标题行,没有部分填充的订单等。

  3. 由于您正在使用PDO 停止进行查询字符串插值。学习并使用prepared statements

  4. 一旦开始使用预准备语句,您不仅可以使事情变得更加安全,还可以加快订单详细信息行的插入速度。

  5.   

    是的,我使用AUTO_INCREMENT并在执行前准备所有插入:$ query = $ connection-&gt; prepare($ sql); $查询 - &GT;执行();我只是不明白你的第二个解释。

    你目前正在做的事情是无用而危险的。您将查询与值连接(在您的情况下没有任何准备可以这么说),而不是在查询中使用占位符,然后使用绑定值。

    更新:以下是您的看法

    $colour = array_filter($product['colour']);
    
    $connection->beginTransaction(); // Turn off auto commit and explicitly open transaction
    
    $sql = "INSERT INTO orders (customer_id, customer_name, order_price, order_date) 
            VALUES (?,?,?,?)"; // Use placeholders in the query. You can use named placeholders if you want to
    $query = $connection->prepare($sql); // Prepare the statement
    $query->execute(array(
        $customer_id, 
        $user['customer_name'], 
        $total_price, 
        $date)
    ); // Bind the values and execute the statement
    
    $respective_order_id = $connection->lastInsertId();
    
    $sql = "INSERT INTO purchased_products (order_id, product_name, product_price, quantity, colour) 
            VALUES (?,?,?,?,?)";
    $query = $connection->prepare($sql); // Prepare once !!!
    
    foreach($_SESSION['cart'] as $product) {
        $query->execute(array(
            $respective_order_id,
            $product['product_name'],
            $product['product_price'],
            $product['quantity'],
            empty($colour) ? null : $product['colour']['colour_name'], //you can bind null value for nullable columns
        )); // Bind and execute multiple times
    }
    // Explicitly commit the transaction
    $connection->commit();