php - PDO Insert 将值 1 写入具有绑定(bind)参数的所有字段

标签 php mysql

我有一个包含以下字段/数据类型的联系人表:contactid(PK,自动递增,不为空),fname varchar(50)lname varchar(50)email varchar(50)is_member tinyint(1)(即 bool 值)和 createdate date.

数据被提交到表单所在的同一 PHP 页面,$_POST 数组的值被打包到 Contact 对象中并传递给以下函数:

<?php
    public static function insertContact(Model $model, Contact $contact) {
        $database = new Database();
        $sql = 'INSERT INTO contact (fname, lname, email, is_member, createdate) VALUES (:fname, :lname, :email, :is_member, CURDATE())';
        $params = array(
            ':fname' => $contact->getFirstname(),
            ':lname' => $contact->getLastname(),
            ':email' => $contact->getEmail(),
            ':is_member' => intval($contact->isMember())
        );
        $result = $database->query($sql, $params, 'LASTID'); // Will return last inserted ID.
        $model->notify('Added contact ID ' . strval($result) . ' to the database.');
    }
?>

如果另一个检查联系人是否已存在的函数返回false,则调用此函数。我正在使用 PDO 准备好的语句,并且 SELECT 语句一切正常,但是当我尝试执行此 INSERT 语句时,我遇到了问题。 $params 数组是正确的,并且参数的数量与占位符的数量匹配,但 is_member 字段导致了问题。如果值为 1,则 INSERT 完成,但结果行如下所示:

contactid  fname  lname  email  is_member  createdate
14         1      1      1      1          2014-05-31

Has anybody seen this behavior before? Moreover, if the value of is_member is 0, then the query fails entirely with the PDOStatement warning [HY093]: Invalid parameter number: number of bound variables does not match number of tokens. What I don't get is that $params has the correct number of values to bind to the placeholder tokens.

[UPDATE:] The $database->query() method is as follows:

<?php
    // Return type is the format in which to return the result of the query.
    public function query($sql, $params, $returnType) {
        if($stmt = $this->connection->prepare($sql)) {
            foreach($params as $key => $value) {
                if($value != 'noParams') {
                    $stmt->bindParam($key, $value);
                }
            }
            if($stmt->execute()) {    // execute() returns TRUE on success
                 switch($returnType) {
                     case 'ASSOC':
                         $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
                     break;
                     case 'LASTID':
                         $result = $this->connection->lastInsertId();
                     break;
                     // ... more cases, etc.
                 }
             } else {
                 $result = null;
                 die('Error: ' . $this->connection->error);
             }

             return $result;
         } else {
             die('Prepare failed: (' . $this->connection->error . ')');
         }
     }
?>

如上所述,此 query() 方法适用于 SELECT 操作的准备语句,但是在尝试执行简单的 INSERT 时,它会表现出上述行为。任何帮助表示赞赏!谢谢!

最佳答案

第一个问题:

if($value != 'noParams') {

如果值为 0,则这将是错误匹配,因为它是松散类型比较;因此“falsey”类型值(null0.0false 等)会给您带来问题,因为它不会绑定(bind)任何 falsey 值来自您的数组...这解释了您的无效参数编号:绑定(bind)变量的数量与 token 数量不匹配错误...

进行严格比较:

if($value !== 'noParams') {

你的第二个问题:

引自PHP Docs

Unlike PDOStatement::bindValue(), the variable is bound as a reference and will only be evaluated at the time that PDOStatement::execute() is called.

在实际执行语句时,$value 仅具有绑定(bind)循环最后一次迭代的值,即来自 is_member 数组的值元素,即 1。这就是为什么您只得到所有绑定(bind)变量的 1

foreach 循环更改为

foreach($params as $key => &$value) {

因此 $value 是“通过引用”,并且它应该是绑定(bind)到每个绑定(bind)变量的正确引用

或者,使用 bindValue() 而不是 bindParam()

整体:

为了完整修复

foreach($params as $key => &$value) {
    if($value !== 'noParams') {
        $stmt->bindParam($key, $value);
    }
}

关于php - PDO Insert 将值 1 写入具有绑定(bind)参数的所有字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23971989/

相关文章:

php - Codeigniter - 重命名 Controller 301 重定向旧 url

php - 在 Laravel 5.4 中将外键 bigInteger 设置为 bigIncrements

java - 从 android 发布到 mysql 时出错

javascript - SQL 更新使用 Datepicker.js 将日期重置为 0000-00-00

mysql - 将 2 列同一个表与另一列连接起来

php - 使用先前值加上当前值更新每一行

php - Laravel 5.3 形式的 TokenMismatchException

mysql - 如果数据库表列可以为空,即使我在后端使用验证时强制它不为空,这是否重要?

php - 如何同时从两个网站注销 - PHP Session 处理

php - 使用 PHP PECL 查询 Apache Solr 中的字段