PDO bindParam不在循环中工作

时间:2018-04-05 16:59:40

标签: php pdo bindparam

我无法让bindParam在foreach循环中工作。如果我在循环之外使用bindParam或将值硬编码到sql查询中,一切都很完美。根据{{​​3}},建议使用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”。现在它的方式应该是真的,它的值为false。

解决方案:

事实证明这里有两个问题。我通过在bindParam中使用基本变量而不是数组来跟踪IncredibleHat的答案。这有助于解决第一个问题,但另一个问题是我需要将一些数据强制转换为int:

$pt1 = (int)$installed_version_parts[1];

我原以为PDO::PARAM_INT正在为我做这件事,但事实并非如此。

1 个答案:

答案 0 :(得分:1)

尝试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]));
}