2009-11-13 67 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