2013-02-02 154 views
0

我寫了下面的函數來構造和執行一個帶有鍵值綁定的SQL語句。我使用bindValue()將鍵值對的數組綁定到SQL字符串中的相應標識符。 (echo語句用於調試)。爲什麼在這種情況下PDO :: bindValue()失敗?

public function executeSelect($sql, $bindings = FALSE) 
{ 
    $stmt = $this->dbPDO->prepare($sql); 

    if ($bindings) 
    { 
     foreach($bindings as $key => $value) 
     { 
      $success = $stmt->bindValue($key, $value); 
      echo "success = $success, key = $key, value = $value<br />"; 
      if (!$success) 
      { 
       throw new Exception("Binding failed for (key = $key) & (value = $value)"); 
      } 
     } 
    } 

    echo "Beginning execution<br />"; 
    if ($stmt->execute()) 
    { 
     return $stmt->fetchAll(PDO::FETCH_ASSOC); 
    } 
    else 
    { 
     return FALSE; 
    } 
} 

輸入這個功能如下:

$stmt = "SELECT * FROM test WHERE id = :id"; 
$bindings = array(":id" => "3", ":Foo" => "Bar"); 

在通過$綁定數組的第二個循環,我期望$成功,以評估爲false,從而引發自定義異常,因爲「Bar」不能綁定到「:Foo」,因爲「:Foo」在輸入SQL中不存在。

相反,$成功的計算結果爲真(1)爲$綁定陣列中兩個鍵值對,和一個PDOException被拋出 - >執行()"(HY000)SQLSTATE[HY000]: General error: 25 bind or column index out of range"

爲什麼不bindValue返回false?

+0

此外,我知道沒有語句驗證以確保只有SELECT語句被接受;這是在工作中。 – TeaPow

+0

大概你也只使用'SELECT'權限使用MySQL帳戶? :) –

回答

1

因爲它這樣工作。
它會在綁定時拋出錯誤,但在執行時拋出錯誤。就這樣。

所以,沒有必要循環,你可以使你的方法更短。

public function executeSelect($sql, $bindings = FALSE) 
{ 
    $stmt = $this->dbPDO->prepare($sql); 
    $stmt->execute($bindings); 
    return $stmt->fetchAll(PDO::FETCH_ASSOC); 
} 

我相信也不需要檢查執行結果。
如果出現錯誤,則會引發異常。順便說一句,我會根據這一個做一些幫助函數,返回標量值和單行。他們是非常有用的。雖然我發現有名的佔位符有點沉悶。比較此代碼:

$name = $db->getOne("SELECT name FROM users WHERE group=?i AND id=?i",$group,$id); 
vs. 
$sql = "SELECT name FROM users WHERE group=:group AND id=:id"; 
$name = $db->getOne($sql,array('group' => $group, 'id' => $id)); 

命名需要比匿名多2倍的代碼。
WET首字母縮寫詞的完美示例 - 「Write Everything Twice」

+0

感謝您的反饋。我有一種感覺,這不是一個錯誤,但如果指定的佔位符不存在於語句中,我會預期會拋出一個錯誤。或者至少,我就是這麼設計的。 – TeaPow

相關問題