0

我正在更新我的 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 作为最佳实践 - 这是正确的还是我可以去执行()?

任何帮助表示赞赏

4

3 回答 3

2

您正在从错误的一端提起此日志。
您的方法可能不安全,但同时又不灵活。如果您需要基于 JOIN 的更新怎么办?如果您需要 OR 在 WHERE(或 IN)中怎么办?

您真正需要的是一个传统查询,其中只需要生成 SET 语句值。因此,您需要一个辅助函数来从数据数组中生成这样的语句,返回格式正确的 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 中提到的那样)

于 2013-03-27T09:27:39.253 回答
1

我相信问题在于您正在使用 foreach 将参数绑定到查询。为什么这是个问题?因为当你绑定一个变量时,你绑定了一个对那个变量的引用,所以如果那个变量改变了,查询中的值也会改变。由于您使用的是 foreach 循环,因此所有参数的值将是变量 $value 引用的最新值。

您可以在此处此处阅读有关此 foreach 行为的更多信息。所以基本上,你有两个选择:

  • 使用对实际值的引用,而不是使用对 $value 的引用(可以在下一次迭代中更改其值)
  • 使用一个辅助变量来引用另一个在循环期间不会改变的内存位置
于 2013-03-27T09:08:22.630 回答
0

我来到这里是因为我遇到了同样的问题,而 YCS 的解决方案正是我所需要的。对于这种情况下的其他任何人,这是我最终使用的辅助函数:

函数 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);

}

于 2014-07-09T20:50:18.620 回答