我正在尝试创建一个订单/发票系统。
我有一个表用于orders
,一个表用于行项目:orders_items
。
我正在尝试使用PDO::ATTR_EMULATE_PREPARES
属性一次性插入所有行项目。
我了解安全风险,没有用户输入进入此数据库。这都是幕后的事情。
当我解析$order_item
数组时,我正在使用占位符创建多个 INSERT sql 语句。
但是,当我去绑定参数时,数据库中似乎只添加了$order_item
数组中的最后一项。
以下是$data
变量查找$order_item
数组的方式。
array(2) {
[0]=>
array(4) {
["name"] => string(8) "A red item"
["quantity"]=> int(1)
["price"] => string(1) "1"
["order_id"]=> string(2) "44"
}
[1]=>
array(4) {
["name"] => string(9) "A blue item"
["quantity"]=> int(1)
["price"] => string(1) "2"
["order_id"]=> string(2) "44"
}
}
构建插入语句将创建以下内容:
INSERT INTO orders_items ( name, quantity, price, order_id ) VALUES ( :name, :quantity, :price, :order_id );
INSERT INTO orders_items ( name, quantity, price, order_id ) VALUES ( :name, :quantity, :price, :order_id );
在占位符值绑定阶段,我试图做的是这样的:
:name = "A red item", :quantity = 1, :price = 1, :order_id = 44
:name = "A blue item", :quantity = 1, :price = 2, :order_id = 44
但只有这个入到数据库中:
:name = "A blue item", :quantity = 1, :price = 2, :order_id = 44
这是我的创建函数
public static function create ($data = []) {
$order_info = $data['order_info'];
$orderID = //do first insert and get the record ID
$order_item = $data['order_item'];
//Attach the order number to the each item in the $order_item array
//This way during the SQL for each, the order_id, which is a required column, will be added
foreach ($order_item as $key=>$value){
$order_item[$key]["order_id"] = $orderID;
}
//Build the INSERT statements
$sql = "";
foreach ($order_item as $item){
$sql .= "INSERT INTO orders_items ";
$sql .= " ( " . implode(", ", array_keys($item)) . " )";
$sql .= " VALUES ( :" . implode(", :", array_keys($item)) . " ); ";
}
$db = static::getDB();
$db->setAttribute( PDO::ATTR_EMULATE_PREPARES, 1 );
$stmt = $db->prepare( $sql );
//BIND ALL THE ORDER ITEM PLACEHOLDERS TO THEIR VALUES.
foreach ($order_item as $item) {
foreach ($item as $linekey => $linevalue) {
$stmt->bindValue(":" . $linekey, $linevalue, PDO::PARAM_STR);
}
}
return $stmt->execute();
}
我做错了什么?这可能吗?有没有更好的方法?
我会这样做,它要简单得多:
$cols = implode(',', array_keys($order_item[0]));
function colon_prefix($param) { return ":$param"; }
$params = implode(',', array_map("colon_prefix", array_keys($order_item[0])));
$sql = "INSERT INTO orders_items ($cols) VALUES ($params)";
$stmt = $db->prepare($sql);
foreach ($order_item as $item) {
$stmt->execute($item);
}
您可以多次重新执行预准备语句,将不同的数组传递给每次执行。这与多查询代码一样好,并且更容易编码和阅读。
我从不使用多查询(一个 SQL 查询字符串中的多个语句(。做对很复杂,而且这样做没有任何好处。
绑定参数的值时,一次必须在键上放置冒号前缀以匹配参数占位符。但是他们很久以前就修复了这个问题,甚至他们修复它的PHP版本现在也被弃用了。可以使用纯字符串作为绑定密钥。
您根本不需要使用bindValue()
,只需将数组传递给execute()
即可。
此外,上面的代码假设您的列名不需要分隔。也就是说,它们不是 SQL 保留字,并且不包含空格、标点符号或国际字符等特殊字符。
获取索引元素总和后在for循环中打印。
$arr_count = count($array);
for($i = 0; $i <= $arr_count; $i++){
$insert_ord_query = $dbh->prepare("INSERT INTO orders(name, quantity, price, order_id) VALUES(:name, :quantity, :price, :order_id)");
$inser_ord_query->execute(array(
":name" => $array[$i]['name'],
":quantity" => $array[$i]['quantity'],
":price" => $array[$i]['price'],
":order_id" => $array[$i]['order_id']
));
}
echo "success";