2009-11-13 47 views
1

有人可以帮我看看有什么与此设置PDO数据库抽象

我建@sql查询下面这样的功能会错。 额外的引号是在条件数组中设置的。

 $sql .= " WHERE $field = \"$value\""; 

pdo update函数像这样循环条件数组。

if (!is_null($conditions)) 
{ 
$cond = ' WHERE'; 
$obj = new CachingIterator(new ArrayIterator($conditions)); 
foreach($obj as $k=>$v) 
{ 
    $cond .= " $k=$v"; 
    $cond .= $obj->hasNext() ? ' AND' : ''; 
} 
} 

我要指出的是,我不能建立值的数组没有添加引号围绕值的数组。 否则,正在抛出的sql错误是它是一个未知的列。

有什么其他的我可以做吗?

有人可以给我一些这方面的意见。

编辑:其余关闭更新功能

我在哪里可以结合的条件数组的值,并让他们 也执行?正如我现在看到的,只有值数组被执行? 我是否需要循环两个数组然后合并两个数组?

$obj = new CachingIterator(new ArrayIterator($values)); 

      $db = db::getInstance(); 
      $sql = "UPDATE $table SET \n"; 
      foreach($obj as $field=>$val) 
      { 
       $sql .= "$field= :$field"; 
       $sql .= $obj->hasNext() ? ',' : ''; 
       $sql .= "\n"; 
      } 

      $sql .= $cond ; 
      $stmt = $db->prepare($sql); 

      // bind de params 
      foreach($values as $k=>$v) 
      { 
       $stmt->bindParam(':'.$k, $v); 
      } 


      $stmt->execute($values); 

感谢,理查德

回答

1

请勿使用addslashes()。这是逃避价值观的一种不充分的方式,并且存在安全漏洞。

标准SQL中的双引号用于分隔标识符。对字符串使用单引号。

MySQL的默认模式允许您交替使用单引号和双引号,并为分隔标识符使用反引号。但我建议养成只使用单引号字符串的习惯,因为它使您的SQL代码更易于移植到其他RDBMS供应商,并且读取代码的任何人都更加清楚。

您应该使用查询参数,正如@Mike B所示。这很容易,并且比将变量插入到SQL表达式中更安全。


您可以使用bindParam(),或者你可以提供一个$values关联数组到​​功能。两者都是多余的。

请注意,你给​​方法阵列不必有:字符前面加上占位符名称:

$stmt = $pdo->prepare("SELECT * FROM MyTable WHERE myfield = :myfield"); 
// both of the following would work: 
$stmt->execute(array(":myfield" => $value)); 
$stmt->execute(array("myfield" => $value)); 

而且支持同时在SET子句和WHERE子句的参数,我'd建议您在指定参数占位符名称时区分字段。这样,如果你引用两个子句中的相同字段(一个搜索旧值,另一个设置新值),则不会发生冲突。

也许":set$field"SET子句和":where$field"WHERE子句。


更新:我已经测试了下面的代码。首先,我使用普通数组,而不是使用的CachingIterator。我不需要使用hasNext()方法,因为我使用的是join()

$settings = array("myfield" => "value"); 
$conditions = array("id" => 1); 

$sql = "UPDATE $table SET \n"; 

下一步是使用array_map()join(),而不是循环的演示。我使用PHP 5.3.0,所以我可以使用内联闭包函数。如果您使用早期版本的PHP,则必须先声明函数并将其用作回调函数。

$sql .= join(",", 
    array_map(
     function($field) { return "$field = :set$field"; }, 
     array_keys($settings) 
    ) 
); 

if ($conditions) 
{ 
    $sql .= " WHERE " 
    . join(" AND ", 
     array_map(
      function($field) { return "$field = :where$field"; }, 
      array_keys($conditions) 
     ) 
    ); 
} 

$stmt = $db->prepare($sql); 

我不能让bindParam()工作,它总是添加值“1”,而不是在我的数组的实际值。因此,这里的编写代码的关联数组,并把它传递给​​:

$params = array(); 
foreach ($settings as $field=>$value) { 
    $params[":set$field"] = $value; 
} 
foreach ($conditions as $field=>$value) { 
    $params[":where$field"] = $value; 
} 

$stmt->execute($params); 
+0

谢谢,这很有帮助,我已经在一个函数中构建了4个循环,因为我对此不太熟悉。但我必须仔细观察一下。 – Richard 2009-11-13 20:30:14

+1

你可以通过使用'array_map()'和'join()'来代替所有这些循环来加强你的代码。 – 2009-11-13 20:36:53

+0

谢谢,你在哪里更快,我从来没有使用过这些函数,所以我会看看这个也 – Richard 2009-11-13 20:50:29

4

如果您使用PDO,为什么不使用bindParam()bindValue()方法demonstated here

+0

,谢谢,我会研究,如果消除了该问题 – Richard 2009-11-13 19:29:21

+0

能你也有更多然后一个阵列场/值? 一个用于更新,另一个用于条件。 因为如果我看到这个 - :$ stmt-> execute($ values);那么只有一个与参数绑定的数组被执行? – Richard 2009-11-13 19:50:39