2013-03-27 34 views
0

我正在更新我的mysql函数以使用PDO。我已经掌握了大部分的内容,但正在努力使用更新功能来更新记录中的多个字段。 功能是在一类,我试图保持它灵活的与其他表等使用Php和pdo创建灵活的更新查询 - 使用bindparam的问题

重用这里是我的功能至今:

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

您可以编写生成的SQL是什么样子? – fiunchinho 2013-03-27 09:01:53

回答

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

再回到你的问题,一个是正确的 - 你需要使用bindValue而不是bindParam(正如它在标记wiki中提到的那样)

+0

我更新了bindvalue来解决当前的问题。我必须承认,对于我的学习清单创建帮助函数是一种天真的想法 – Ray 2013-04-08 09:43:37

1

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

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

  • 使用参考实际值,而不是使用到$值的参考(可以在下次迭代改变它的值)
  • 使用附配变量引用另一个内存位置不会在循环中改变
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); 

}