我正在更新我的mysql函数以使用PDO。我已经掌握了大部分内容,但正在努力使用更新功能来更新记录中的多个字段。 该函数在一个类中,我试图保持其灵活性,以便与其他表等重用。
到目前为止,这是我的功能:
public function dbUpdateRecord($table, $values, $where)
{
$this->conn();
$fieldNames = array_keys($values);
var_dump($fieldNames);
$set="";
foreach ($fieldNames as $field) {
$set .= " $field = :$field,";
}
//strip last comma
$set = substr($set, 0, strlen($set) - 1);
$wherefields = array_keys($where);
$whereCondition="";
foreach ($wherefields as $field) {
$whereCondition .= " $field = :$field AND";
}
//strip last AND
$whereCondition = substr($whereCondition, 0, strlen($whereCondition) - 3);
$sql = "UPDATE $table SET $set WHERE $whereCondition";
var_dump($sql);
$stmt = $this->db->prepare($sql);
foreach ($values as $field => $value) {
$stmt->bindParam(':$field', $value);
}
foreach ($where as $field => $value) {
$stmt->bindParam(':$field', $value);
}
return $stmt->execute();
}
问题是记录中的所有字段都是由$ where变量中包含的记录的id更新的。
$ values包含一个(fieldname => value)数组。
我认为问题在于bindparam并试图使字段名/占位符动态
我认为我需要使用bindparam作为最佳实践 - 这是正确的还是我可以去执行()?
非常感谢
答案 0 :(得分:2)
您正在从错误的一端解除此日志 您的方法可能不安全但同时又不灵活。 如果您需要基于JOIN的更新怎么办?如果在WHERE(或IN)中需要OR怎么办?
您真正需要的是传统查询,其中只需要生成SET语句值。 因此,您需要一个helper function to produce such a statement数据数组,返回正确格式化的SET语句和带有要绑定的变量的数组:
$fields = array("name","email");
$sql = "UPDATE users SET ".pdoSet($fields,$values,$data)." WHERE id = :id"
// now we have $values array to be passed into query
$stmt = $dbh->prepare();
$values["id"] = $_POST['id'];
$stmt->execute($values);
使用此代码,您将能够为任意查询进行更新。并使其安全。
作为进一步的步骤,您需要开始使用类型提示的占位符,以便像这样生成整个代码:
$db->query("UPDATE ?n SET ?u WHERE id IN(?a)",$table,$data,$ids);
回到你的问题,ONe是对的 - 你需要使用bindValue而不是bindParam(正如它在标签wiki中提到的那样)
答案 1 :(得分:1)
我认为问题在于你使用foreach将params绑定到查询。为什么这是个问题?因为绑定变量时绑定对该变量的引用,所以如果该变量发生更改,查询中的值也会更改。由于您使用的是foreach循环,因此所有参数的值将是变量$ value引用的最新值。
您可以详细了解此foreach行为here和here。所以基本上,你有两个选择:
答案 2 :(得分:0)
我来到这里是因为我遇到了同样的问题,YCS的解决方案就是我所需要的。对于这种情况下的其他任何人,这里是我最终使用的辅助函数:
function commit_table($ record_id,$ changed_values) { $ db = open_database();
$query = 'UPDATE table SET ';
$query_arguments = array();
$is_first = TRUE;
foreach(array_keys($changed_values) as $key)
{
if($is_first)
{
$is_first = FALSE;
}
else
{
$query .= ', ';
}
$value_var = ':' . $key;
$query .= $key;
$query .= ' = ';
$query .= $value_var;
$query_arguments[$value_var] = $changed_values[$key];
}
$query .= ' WHERE record_id = :record_id';
$query_arguments[':record_id'] = $record_id;
$stmt = $db->prepare($query);
$stmt->execute($query_arguments);
close_database($db);
}