gpt4 book ai didi

php - 日期不工作的 PDO bindParam

转载 作者:行者123 更新时间:2023-11-29 05:11:39 40 4
gpt4 key购买 nike

我是 PDO 的初学者,我正在制作一个 php 函数来返回航类的搜索结果,这是我的代码:

$db = DB::getConnection();
$stmt = $db->prepare("SELECT * FROM `flights` WHERE `date` BETWEEN :befDate AND :aftDate
AND `from` = :from
AND `to` = :to
AND `weight` >= :weight");
$stmt->bindParam(':befDate', $befDate, PDO::PARAM_STR); //$befDate = '2016-07-21';
$stmt->bindParam(':aftDate', $aftDate, PDO::PARAM_STR); //$aftDate = '2016-07-28';
$stmt->bindParam(':from', $from, PDO::PARAM_INT);
$stmt->bindParam(':to', $to, PDO::PARAM_INT);
$stmt->bindParam(':weight', $weight, PDO::PARAM_INT);
$ok = $stmt->execute();
if ($ok) {
if ($stmt->fetchColumn()>=1) {
$result = $stmt->fetchAll();
}
else{
$result = 'nope';
}
return $result;
}
else{
return false;
}

问题是,它总是返回 0 个搜索结果。我尝试在 phpMyAdmin 中手动运行通过函数生成的 SQL,发现问题是因为 PDO 生成的 SQL 是:

"SELECT * FROM `FLIGHTS` WHERE `DATE` BETWEEN 2016-07-17 AND 2016-07-25 AND `FROM` = 1237 AND `TO` = 2380 AND `WEIGHT` >= 4"

虽然我从中获得结果的正确 SQL 应该是:

"SELECT * FROM `FLIGHTS` WHERE `DATE` BETWEEN '2016-07-17' AND '2016-07-25' AND `FROM` = 1237 AND `TO` = 2380 AND `WEIGHT` >= 4"

即,在单引号之间包含日期值。现在,如果我在 PDO 中向我的 SQL 添加引号,例如:

$stmt = $db->prepare("SELECT * FROM `flights` WHERE `date` BETWEEN ':befDate' AND ':aftDate' 
AND `from` = :from
AND `to` = :to
AND `weight` >= :weight");

我收到“无效参数编号:绑定(bind)变量的数量与标记的数量不匹配”错误。提前感谢您的帮助!

更新:

我的“航类”表结构是:

CREATE TABLE `flights` (
`fid` int(30) NOT NULL,
`user_id` int(30) NOT NULL,
`date` date NOT NULL,
`from` int(30) NOT NULL,
`to` int(30) NOT NULL,
`weight` int(30) NOT NULL,
`size` varchar(30) NOT NULL,
`details` varchar(200) NOT NULL,
`price` int(50) NOT NULL,
`airline` varchar(100) NOT NULL,
`pnr` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

我尝试从查询中删除所有引号并将其也放在一个完整的行中:

$stmt = $db->prepare("SELECT * FROM flights WHERE date BETWEEN :befDate AND :aftDate AND from = :from AND to = :to AND weight >= :weight");

但还是不行...

更新 2为了确定在将参数与 PDO 绑定(bind)后 SQL 语句的样子(没有单引号的语句),我在函数的开头创建了一个与我的 SQL 相同的 session 变量,并回显它以查看结果:

$_SESSION['err'] = "SELECT * FROM flights WHERE date BETWEEN $befDate AND $aftDate 
AND from = $from
AND to = $to
AND weight >= $weight";

最佳答案

这是您的主要问题:

if ($stmt->fetchColumn()>=1) {
$result = $stmt->fetchAll();
}
else{
$result = 'nope';
}

对 fetchColumn() 的调用将结果集推进到其第一行之后。然后,当您调用 fetchAll() 时,它只会获取 剩余 行。它不能返回并获取第一行,那已经丢失了。因此,如果您的查询结果只有一行,您将永远看不到它。

相反,我建议使用以下代码:

$result = $stmt->fetchAll();
if (empty($result)) {
$result = "nope";
}

其他提示:

切勿将参数占位符放在引号内。如果这样做,它们就不再是参数占位符,它们只是像“:befDate”这样的文字字符串。这些不是有效的日期文字。

BETWEEN :befDate AND :aftDate 等表达式中的参数不会生成 BETWEEN 2016-07-17 AND 2016-07-25 作为查询。参数永远不会成为那样的表达式,它们总是成为每个参数的标量值(例如带引号的日期文字)。

我试过你的代码。首先,我启用了 MySQL 通用查询日志:

mysql> SET GLOBAL general_log = ON;

现在我可以准确地看到 MySQL 认为 PDO 提交的查询是什么了。我运行了 PHP 脚本,并阅读了我的一般查询日志(我的虚拟机上的/var/lib/mysql/localhost.log):

160716 19:26:16     8 Connect   root@localhost on test
8 Query SELECT * FROM `flights` WHERE `date` BETWEEN NULL AND NULL
AND `from` = NULL
AND `to` = NULL
AND `weight` >= NULL
8 Quit

啊,我忘了为绑定(bind)到参数的变量设置值。如果这些变量中的任何一个都没有值,这将解释为什么结果为空,因为与 NULL 的任何比较都是不正确的。所以我编辑了 PHP,首先将示例值设置为变量。

$befDate = '2016-07-21';
$aftDate = '2016-07-28';
$from = 1;
$to = 2;
$weight = 10;

我再次运行查询,并在日志中看到以下内容:

160716 19:33:17    13 Query SELECT * FROM `flights` WHERE `date` BETWEEN '2016-07-21' AND '2016-07-28' 
AND `from` = 1
AND `to` = 2
AND `weight` >= 10

这证明 PDO 确实在参数化值周围加上引号(如果它是字符串或日期)。

关于php - 日期不工作的 PDO bindParam,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38414507/

40 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com