PDO bindParam 不在循环中工作
PDO bindParam not working in loop
我无法让 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();
}
我的预期结果是在终端上显示 "Found: 1"。现在的样子,它应该为真时却有假值。
解法:
原来这里有两个问题。我通过在我的 bindParam 中使用基本变量而不是数组来遵循 IncredibleHat 的回答。这有助于解决第一个问题,但另一个问题是我需要将一些数据类型转换为 int:
$pt1 = (int)$installed_version_parts[1];
我以为 PDO::PARAM_INT
是为我做的,但事实并非如此。
尝试 bindParam
到像 $array['key']
这样的数组元素会导致一些问题,因为它被绑定为引用,但事实并非如此。它,只是没有那样做。
所以三种方式:
$stmt = $dbh->prepare($sql);
// bind to variables that can be a reference
$stmt->bindParam(":GROUP_ID", $id, PDO::PARAM_INT);
$stmt->bindParam(":INSTALLED_VERSION_NUM_1", $pt1, PDO::PARAM_INT);
$stmt->bindParam(":INSTALLED_VERSION_NUM_2", $pt2, PDO::PARAM_INT);
foreach ($installed_groups as $installed_group){
$installed_version_parts = explode('.', $installed_group['version']);
// assign the referenced vars their new value before execute
$id = $installed_group['group_id'];
$pt1 = $installed_version_parts[1];
$pt2 = $installed_version_parts[2];
$stmt->execute();
}
或者:(效率较低)
$stmt = $dbh->prepare($sql);
foreach ($installed_groups as $installed_group){
$installed_version_parts = explode('.', $installed_group['version']);
// use bindValue (not bindParam) INSIDE the loop
// bindValue doesn't set them by reference, so any value expression works
$stmt->bindValue(":GROUP_ID", $installed_group['group_id'], PDO::PARAM_INT);
$stmt->bindValue(":INSTALLED_VERSION_NUM_1", $installed_version_parts[1], PDO::PARAM_INT);
$stmt->bindValue(":INSTALLED_VERSION_NUM_2", $installed_version_parts[2], PDO::PARAM_INT);
$stmt->execute();
}
或:
$stmt = $dbh->prepare($sql);
foreach ($installed_groups as $installed_group){
$installed_version_parts = explode('.', $installed_group['version']);
// pass them on execute directly
$stmt->execute(array(':GROUP_ID'=>$installed_group['group_id'],
':INSTALLED_VERSION_NUM_1'=>$installed_version_parts[1],
':INSTALLED_VERSION_NUM_2'=>$installed_version_parts[2]));
}
我无法让 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();
}
我的预期结果是在终端上显示 "Found: 1"。现在的样子,它应该为真时却有假值。
解法:
原来这里有两个问题。我通过在我的 bindParam 中使用基本变量而不是数组来遵循 IncredibleHat 的回答。这有助于解决第一个问题,但另一个问题是我需要将一些数据类型转换为 int:
$pt1 = (int)$installed_version_parts[1];
我以为 PDO::PARAM_INT
是为我做的,但事实并非如此。
尝试 bindParam
到像 $array['key']
这样的数组元素会导致一些问题,因为它被绑定为引用,但事实并非如此。它,只是没有那样做。
所以三种方式:
$stmt = $dbh->prepare($sql);
// bind to variables that can be a reference
$stmt->bindParam(":GROUP_ID", $id, PDO::PARAM_INT);
$stmt->bindParam(":INSTALLED_VERSION_NUM_1", $pt1, PDO::PARAM_INT);
$stmt->bindParam(":INSTALLED_VERSION_NUM_2", $pt2, PDO::PARAM_INT);
foreach ($installed_groups as $installed_group){
$installed_version_parts = explode('.', $installed_group['version']);
// assign the referenced vars their new value before execute
$id = $installed_group['group_id'];
$pt1 = $installed_version_parts[1];
$pt2 = $installed_version_parts[2];
$stmt->execute();
}
或者:(效率较低)
$stmt = $dbh->prepare($sql);
foreach ($installed_groups as $installed_group){
$installed_version_parts = explode('.', $installed_group['version']);
// use bindValue (not bindParam) INSIDE the loop
// bindValue doesn't set them by reference, so any value expression works
$stmt->bindValue(":GROUP_ID", $installed_group['group_id'], PDO::PARAM_INT);
$stmt->bindValue(":INSTALLED_VERSION_NUM_1", $installed_version_parts[1], PDO::PARAM_INT);
$stmt->bindValue(":INSTALLED_VERSION_NUM_2", $installed_version_parts[2], PDO::PARAM_INT);
$stmt->execute();
}
或:
$stmt = $dbh->prepare($sql);
foreach ($installed_groups as $installed_group){
$installed_version_parts = explode('.', $installed_group['version']);
// pass them on execute directly
$stmt->execute(array(':GROUP_ID'=>$installed_group['group_id'],
':INSTALLED_VERSION_NUM_1'=>$installed_version_parts[1],
':INSTALLED_VERSION_NUM_2'=>$installed_version_parts[2]));
}