将订单 ID 与属于它的产品相关联的最佳方式
Best way to relate the order ID with the products that belongs to it
我正在开发一个商店系统,并且我正在使用我能够找到的唯一方法将订单 ID 与属于它的产品相关联。
当有人购买东西时,首先将订单及其详细信息添加到 table orders
,包括该订单的 ID (order_id
),该 ID 由 [=68= 自动递增].
我用这个给table添加订单 orders
:
INSERT INTO orders SET customer_id = '{$customer_id}', customer_name = '{$user['customer_name']}', order_price = '{$total_price}', order_date = '{$date}'"
好的,订单已添加。现在,按顺序,属于该订单的产品将被添加到另一个 table,table purchased_products
。
我使用 PDO lastInsertId()
来获取最后从 table orders
插入 order_id
,然后在另一个 table table 中添加该订单的每个产品 Foreign Key
order_id
18=]。为此,我使用:
$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
table 中,其 order_id
自动递增,然后该订单的所有产品也将添加到 purchased_products
table 和其中每一个的 Foreign Key
order_id
将具有插入 orders
table 中的最后一个 order_id
的值。稍后我将可以通过使用外键 order_id
.
查询它们的产品来显示任何订单。到目前为止,它运行良好。正如我所说,这是我找到的将订单 ID 分配给属于它的产品的唯一方法。我的问题是:这安全吗?如果几个人同时购买呢?是否存在更换 ID 或未 added/or 的产品走错订单的风险?如果有经验的人回答这些问题,我将不胜感激,因为这让我很害怕,我想知道我是否可以信任这种方法。
编辑
更多详情!
我的数据库连接:
try
{
$connection = new PDO("mysql:host={$HOST};dbname={$DB_NAME}", $USERNAME, $PASS);
}
catch(PDOException $exception)
{
echo "Connection error: " . $exception->getMessage();
}
我用来在两个table中插入数据的所有代码:
$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();
}
编辑 2 更新
有些产品可以有额外的阵列(即颜色),有些则没有。但所有默认情况下都填充了这些数组:product_name
、product_price
和 product_quantity
。
我已经调整我的逻辑以使用 [= 提供的代码检查额外参数50=]peterm:
$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();
如果SESSION中的额外参数数组不为空,则SQLtable中的colour
键将填充产品颜色。否则,将填充SQL NULL
.
使用 PDO 的 lastInsertId()
依赖于 driver,但只要您使用适当的自动递增类型 object(即MySQL 中的 AUTO_INCREMENT
或 PostgreSQL 中的序列)。 MySQL driver 在后台使用 LAST_INSERT_ID()
。
如果您关心事务完整性,请考虑将整个操作包装到一个事务中。这样,它要么全部正确提交,要么回滚。没有孤立的订单 header 行,没有部分填充的订单等
因为您正在使用 PDO stop 进行查询字符串插值。学习和使用 prepared statements
一旦开始使用准备好的语句,您不仅可以使事情更加安全,而且可以加快订单详细信息行的插入速度。
Yes, I use AUTO_INCREMENT and also prepare in all insertions before execute: $query = $connection->prepare($sql); $query->execute(); I just don't understood your second explanation.
你现在所做的事情既无用又危险。您将查询与值连接起来(可以说您的情况无需准备),而不是在查询中使用占位符然后绑定值。
更新:这是你的样子
$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();
我正在开发一个商店系统,并且我正在使用我能够找到的唯一方法将订单 ID 与属于它的产品相关联。
当有人购买东西时,首先将订单及其详细信息添加到 table orders
,包括该订单的 ID (order_id
),该 ID 由 [=68= 自动递增].
我用这个给table添加订单 orders
:
INSERT INTO orders SET customer_id = '{$customer_id}', customer_name = '{$user['customer_name']}', order_price = '{$total_price}', order_date = '{$date}'"
好的,订单已添加。现在,按顺序,属于该订单的产品将被添加到另一个 table,table purchased_products
。
我使用 PDO lastInsertId()
来获取最后从 table orders
插入 order_id
,然后在另一个 table table 中添加该订单的每个产品 Foreign Key
order_id
18=]。为此,我使用:
$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
table 中,其 order_id
自动递增,然后该订单的所有产品也将添加到 purchased_products
table 和其中每一个的 Foreign Key
order_id
将具有插入 orders
table 中的最后一个 order_id
的值。稍后我将可以通过使用外键 order_id
.
查询它们的产品来显示任何订单。到目前为止,它运行良好。正如我所说,这是我找到的将订单 ID 分配给属于它的产品的唯一方法。我的问题是:这安全吗?如果几个人同时购买呢?是否存在更换 ID 或未 added/or 的产品走错订单的风险?如果有经验的人回答这些问题,我将不胜感激,因为这让我很害怕,我想知道我是否可以信任这种方法。
编辑
更多详情!
我的数据库连接:
try
{
$connection = new PDO("mysql:host={$HOST};dbname={$DB_NAME}", $USERNAME, $PASS);
}
catch(PDOException $exception)
{
echo "Connection error: " . $exception->getMessage();
}
我用来在两个table中插入数据的所有代码:
$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();
}
编辑 2 更新
有些产品可以有额外的阵列(即颜色),有些则没有。但所有默认情况下都填充了这些数组:product_name
、product_price
和 product_quantity
。
我已经调整我的逻辑以使用 [= 提供的代码检查额外参数50=]peterm:
$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();
如果SESSION中的额外参数数组不为空,则SQLtable中的colour
键将填充产品颜色。否则,将填充SQL NULL
.
使用 PDO 的
lastInsertId()
依赖于 driver,但只要您使用适当的自动递增类型 object(即MySQL 中的AUTO_INCREMENT
或 PostgreSQL 中的序列)。 MySQL driver 在后台使用LAST_INSERT_ID()
。如果您关心事务完整性,请考虑将整个操作包装到一个事务中。这样,它要么全部正确提交,要么回滚。没有孤立的订单 header 行,没有部分填充的订单等
因为您正在使用 PDO stop 进行查询字符串插值。学习和使用 prepared statements
一旦开始使用准备好的语句,您不仅可以使事情更加安全,而且可以加快订单详细信息行的插入速度。
Yes, I use AUTO_INCREMENT and also prepare in all insertions before execute: $query = $connection->prepare($sql); $query->execute(); I just don't understood your second explanation.
你现在所做的事情既无用又危险。您将查询与值连接起来(可以说您的情况无需准备),而不是在查询中使用占位符然后绑定值。
更新:这是你的样子
$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();