【发布时间】:2023-03-11 11:41:01
【问题描述】:
我无法让 bindParam 在 foreach 循环内工作。如果我在循环之外使用 bindParam 或将值硬编码到 sql 查询中,一切都会完美运行。根据this page,建议改用bindValue。但是,当我使用 bindValue 时,它说在 bindValue 中使用的三个变量是未定义的。显然他们在这一点上。我做错了什么?
<?php
$found_update = false;
$installed_groups = array(
array(
"group_id" => 14,
"version" => "1.0.7"
)
);
$sql = "select id from testing_set where group_id = :GROUP_ID
and (
substring_index(substring_index(version, '.', 2), '.', -1) > :INSTALLED_VERSION_NUM_1 OR
substring_index(substring_index(version, '.', 3), '.', -1) > :INSTALLED_VERSION_NUM_2
)
order by created desc limit 1";
try {
$dbh = new PDO("mysql:host=localhost; dbname=".DBNAME, DBUSER, DBPWD);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $dbh->prepare($sql);
$stmt->bindParam(":GROUP_ID", $installed_group['group_id'], PDO::PARAM_INT);
$stmt->bindParam(":INSTALLED_VERSION_NUM_1", $installed_version_parts[1], PDO::PARAM_INT);
$stmt->bindParam(":INSTALLED_VERSION_NUM_2", $installed_version_parts[2], PDO::PARAM_INT);
foreach ($installed_groups as $installed_group){
$installed_version_parts = explode('.', $installed_group['version']);
$stmt->execute();
$data = $stmt->fetch(PDO::FETCH_ASSOC);
if (!empty($data)){
$found_update = true;
break;
}
}
echo "Found: $found_update\n";
}
catch(PDOException $e) {
http_response_code(404);
die();
}
我的预期结果是它在终端上显示“找到:1”。现在的样子,当它应该为真时,它的值为假。
解决方案:
原来这里有两个问题。我通过在我的 bindParam 中使用基本变量而不是数组来遵循 IncredibleHat 的回答。这有助于解决第一个问题,但另一个问题是我需要将一些数据类型转换为 int:
$pt1 = (int)$installed_version_parts[1];
我原以为 PDO::PARAM_INT 正在为我做这件事,但事实并非如此。
【问题讨论】:
-
绑定实际变量。
-
@IncredibleHat 是的,但是绑定应该在循环之外完成,而变量直到循环中才存在。这是一个陷阱 22。
-
这看起来应该可以工作,如果explode 产生一个至少有3 个元素的数组,但是尝试一个像
list($z, $one, $two) = explode(.....)这样的临时变量并在绑定调用中使用它们。还有error_reporting(E_ALL); ini_set('display_errors', '1'); -
我认为你应该在循环中绑定并在循环内执行。有了你所拥有的,你应该得到一个未定义的变量,因为这些变量只在循环内可用
-
我遇到的问题是试图将绑定参数(引用)绑定到
$array['key']之类的东西......它会抛出未定义的键。而且它是一个数组项,而不是一个变量。您可以只传递三个项目的执行数组:$stmt->execute(array($installed_group['group_id'],$installed_version_parts[1],$installed_version_parts[2]));并完全取消 bindParam。