2013-02-02 55 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

相关问题