Php PDO bindParam在循环中不工作

Php PDO bindParam在循环中不工作,php,pdo,bindparam,Php,Pdo,Bindparam,我很难让bindParam在foreach循环中工作。如果我在循环外部使用bindParam,或者将值硬编码到sql查询中,那么一切都可以完美地工作。根据调查,建议使用bindValue代替。然而,当我使用bindValue时,它表示bindValue中使用的三个变量是未定义的。很明显,他们在这一点上。我做错了什么 <?php $found_update = false; $installed_groups = array( array(

我很难让bindParam在foreach循环中工作。如果我在循环外部使用bindParam,或者将值硬编码到sql查询中,那么一切都可以完美地工作。根据调查,建议使用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();

    }

我以为
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();
}
或:(效率较低)

或:


绑定实际变量。@不可信是的,但是绑定应该在循环之外完成,而变量只有在循环中才存在。这是一个陷阱22。如果explode生成一个至少包含3个元素的数组,那么它看起来应该可以工作,但请尝试一个临时变量,例如
list($z,$1,$2)=explode(…)
,并在绑定调用中使用这些变量。还有
错误报告(E_ALL);ini_集('display_errors','1')我认为应该在循环中绑定并在循环中执行。就您所拥有的而言,您应该得到一个未定义的变量,因为这些变量仅在循环中可用。我遇到的问题是,试图将bindParam(reference)绑定到类似于
$array['key']
。。。它抛出未定义的键。它也是一个数组项,而不是一个变量。您只需传递一个包含三项的数组即可执行:
$stmt->execute(数组($installed_group['group_id'],$installed_version_parts[1],$installed_version_parts[2])
并完全取消bindParam。我认为第二个选项效率较低是正确的,因为您每次都必须重新绑定,因此第一个或第三个选项最好?正确(对于大型操作)。虽然有一些查询没有注意到这一点。尝试第一个选项只有在我将$pt1和$pt2转换为int时才有效:
$pt1=(int)$installed_version_parts[1]这是为什么?
PDO::PARAM_INT
不应该处理这个问题吗?你会认为它会。。。但是它强制要求它应该是一个int,而不是转换它。这里有一个关于选角的宣传语:(重要的是阅读关于这个答案的论点lol)。
$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]));
}