我有一个包含以下字段/数据类型的联系人表: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”类型值(null
、0.0
、false
等)会给您带来问题,因为它不会绑定(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/