[英]PDO statement updates 0 values instead of null or empty
I am making a PDO update statement but it is entering 0's on empty values.我正在制作 PDO 更新语句,但它在空值上输入 0。
Here is my code:这是我的代码:
include 'dbconfig.php';
$id = $_POST['id'];
$data = $_POST['data'];
try {
$options = [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
\PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = new PDO("mysql:charset=utf8mb4;host=$servername;dbname=$dbname", $username, $password);
$setStr = "";
$values = array();
foreach($data as $field => $value) {
$setStr .= "$field=:$field,";
$values[$field] = $value;
}
$setStr = rtrim($setStr, ",");
$values['id'] = $id;
$stmt = $pdo->prepare("UPDATE products SET $setStr WHERE id = :id");
$stmt->execute($values);
$count = $stmt->rowCount();
if ($count > 0) {
echo json_encode(array('response'=>'success','message'=>'Product ID # '.$id." successfully updated."));
}else{
echo json_encode(array('response'=>'danger','message'=>'Product not successfully updated'));
}
}catch(PDOException $e){
echo json_encode(array('response'=>'danger','message'=>$e->getMessage()));
}
$conn = null;
What is the best way to do this?做这个的最好方式是什么? Thank you谢谢
Check for an empty string in your loop, and convert it to null
.检查循环中的空字符串,并将其转换为null
。
foreach($data as $field => $value) {
$setStr .= "$field=:$field,";
$values[$field] = $value === "" ? null : $value;
}
PDOStatement:: execute considers every parameter to be a string. PDOStatement:: execute认为每个参数都是一个字符串。 In some databases the driver deals with this without issue, but if you want to specifically type values you need instead to use bindValue .在某些数据库中,驱动程序可以毫无问题地处理此问题,但如果您想专门键入值,则需要使用bindValue 。 With this typing, we can type null (or empty) values to the database-null type (instead of whatever the column default is) - see my bindEmptyAsNull
function.通过这种输入,我们可以将 null(或空)值输入到数据库空类型(而不是列默认值) - 请参阅我的bindEmptyAsNull
function。
Also, since I'm using a trusted source for the column names, I can safely use your $setStr
pattern for building the update params, but note you might not want to update a column that isn't included in the $dangerData
associative array (as it is, if it isn't submitted, the column will be cleared).此外,由于我对列名使用了受信任的来源,因此我可以安全地使用您的$setStr
模式来构建更新参数,但请注意您可能不想更新$dangerData
关联数组中未包含的列(原样,如果未提交,该列将被清除)。
<?php
//... your setup code, including $pdo
// List all the names of the columns in the products table here - you havent' provided enough info so I'm guessing
$keys=["name","cost","weight_grams"];
$dangerId = $_POST['id'];
$dangerData = $_POST['data'];
/**
* Convert null values into PARAM_NULL types, not
* @param $type Should be one of the [PDO::PARAM_*](https://www.php.net/manual/en/pdo.constants.php) constants
*/
function bindEmptyAsNull($stmt,$name,$value,$type=PDO::PARAM_STR) {
//If you want empty string to be considered null too:
//if ($value===null || $value==="") {
if ($value===null) {
//Note the column needs to support null types
$stmt->Value($name,null,PDO::PARAM_NULL);
} else {
$stmt->bindValue($name,$value,$type);
}
}
//Build the set string
$setStr='';
foreach($keys as $col) {
$setStr.=$col.'=:'.$col.',';
}
$setStr=substr($set,0,-1);//Remove the trailing comma
//Create the statement
$stmt=$pdo->prepare("UPDATE products SET $setStr WHERE id=:id");
//Bind the danger values
// NOTE: The only way you could automate this (re-read the keys array) is to also have an
// associative array of key:type mapping too
$stmt->bindValue(":id",$dangerId,PDO::PARAM_INT);
bindEmptyAsNull($stmt,":name",$dangerData["name"]);
bindEmptyAsNull($stmt,":cost",$dangerData["cost"]);
bindEmptyAsNull($stmt,":weight_grams",$dangerData["weight_grams"],PDO::PARAM_INT);
$stmt->execute();
// .. Further processing
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.