我有一个联系人表,其中包含以下字段/数据类型:contactid
(PK,自动增量,非null), fname varchar(50)
, lname varchar(50)
, email varchar(50)
, is_member tinyint(1)
(即布尔值)和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
,但结果行看起来像这样:
有人见过这种行为吗?此外,如果is_member
的值为0
,则查询完全失败,PDOStatement警告[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
。我不明白的是$params
有正确数量的值绑定到占位符令牌。
[UPDATE:] $database->query()
方法如下:
<?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') {
如果value为0,那么这将是一个假匹配,因为它是一个松散类型比较;所以"假"类型的值(null
, 0.0
, false
等)会给你带来问题,因为它不会从你的数组绑定任何假值…这解释了你的Invalid parameter number: number of bound variables does not match number of tokens
错误....
使其成为严格的比较:
if($value !== 'noParams') {
你的第二个问题:
引用自PHP文档
与PDOStatement::bindValue()不同,该变量被绑定为引用,并且仅在调用PDOStatement::execute()时才计算。
在实际执行语句时,$value
只有绑定循环最后一次迭代的值,即来自is_member
数组元素的值,即1
。这就是为什么你得到的只有1
值为所有绑定变量
将foreach
循环更改为
foreach($params as $key => &$value) {
因此$value
是"通过引用",然后它应该是绑定到每个绑定变量的正确引用
或者,使用bindValue()
而不是bindParam()
对于完整的修复
foreach($params as $key => &$value) {
if($value !== 'noParams') {
$stmt->bindParam($key, $value);
}
}
您是否尝试过使用exec与查询?
文档中的:http://us1.php.net/manual/en/pdo.exec.php
和http://us1.php.net/pdo.query
bottom line: PDO::query—执行SQL语句,返回结果集作为PDOStatement对象while PDO::exec—执行SQL语句并返回受影响的行数