【问题标题】:php - bind_param inside foreach() not correctly passingphp - foreach() 中的 bind_param 未正确传递
【发布时间】:2013-03-24 10:35:14
【问题描述】:

我确定这是重复的,但我在此处的网站上尝试了几种不同的方法,但没有一种方法适合我。我在 php 中调用我的函数,发送 $mysqli 连接、$clientID 和要上传的 $tagFields 数组。

它正在“工作”,但值始终为空。我已将 echo "$tagName" 放入 foreach 中,它正在读取它,但没有将其发送到数据库。但是,$clientID 正在传递信息。所以基本上它所做的就是将一致的空白行上传到我的数据库中。我在这里做错了什么?

function tagRefresh($mysqli,$clientID,$tagFields) {
    $stmt = $mysqli->stmt_init();
    $query = "INSERT INTO client_tags (client_id,tag_category) VALUES (?,?) ";
    $stmt->prepare($query);
    foreach($tagFields as $tagName) {
        $stmt->bind_param('is',$clientID,$tagName);
        $stmt->execute();
    }
}

$tagFields 的一些示例值:

$tagFields[0] = "Regional";$tagFields[1] = "Automotive";$tagFields[2] = "Maintenance";

【问题讨论】:

  • 我相信bind_param 只绑定到变量的引用。因此,由于您的 foreach 在每次迭代时都会重置 $tagName,因此绑定失败。不幸的是,我在 mysqli 中找不到 bindValue (PDO) 等效项。此外,在您的foreach 完成后,您只需要execute 一次。
  • 你的代码对我有用。
  • @MiroslavStopka,你运行的是什么版本的 php/mysql/apache?
  • @MDWar PHP 版本 5.3.8, MySQL: 5.5.16 , Apache 版本 Apache/2.2.21 (Win32) mod_ssl/2.2.21 OpenSSL/1.0.0e PHP/5.3.8 mod_perl/2.0 .4 Perl/v5.10.1。顺便检查一下你的表 client_tags (列属性...)

标签: php foreach mysqli


【解决方案1】:

注意mysqli_stmt::bind_param绑定变量的引用。 试试下面的:

function tagRefresh($mysqli,$clientID,$tagFields) {
    $stmt = $mysqli->stmt_init();
    $query = "INSERT INTO client_tags (client_id,tag_category) VALUES (?,?) ";
    $stmt->prepare($query);
    $stmt->bind_param('is', $clientID, $tagName);
    foreach($tagFields as $tagName) {
        $stmt->execute();
    }
}

【讨论】:

    【解决方案2】:

    execute() 不应位于 foreach 内。

    【讨论】:

    • 但这也无妨;)
    • 除非意图是多次执行
    • 为什么?您如何建议在没有循环的情况下多次执行此操作?
    • 那么,不要使用准备好的语句吗?这似乎是个坏主意。
    • 为什么必须只调用一次?按照您的建议动态构建查询会阻止使用准备好的语句,这意味着它可能效率较低且安全性较低。重复执行语句正是我们的意图;这就是准备好的语句可以表现出更高效率的地方。这样做本身并没有错。相反,在适当的情况下,它可能是可取的。如果数据都是内部数据并且不包括用户输入,那么按照您的建议构建它可能没问题。如果涉及到用户输入,那么我肯定会使用准备好的语句。
    【解决方案3】:

    在与数据库相关的无数问题中(包括 client_id 作为主键),我重新构建了这样的公式:

    function tagRefresh($mysqli,$clientID,$tagFields) {
        $query = "DELETE FROM client_tags WHERE client_id = '" . $clientID . "'"; //we have to delete the old ones every time
        if(!$mysqli->query($query)) {
            echo $mysqli->error;
        }
    
        if($tagFields != '') { //see if data was sent
            $tags = array();
            foreach($tagFields as $tag) {
                $tags[] = "('" . (int) $clientID . "', '" . $tag ."')"; //build an array
            }
            $query = "INSERT INTO client_tags (client_id,tag) VALUES " . implode(',', $tags) . " ON DUPLICATE KEY UPDATE client_id = " . $clientID;
            if(!$mysqli->query($query)) {
                echo $mysqli->error; //drop errors, will attach this later
            }
        }
    }
    

    这个格式是这样的:

    INSERT INTO client_tags (client_id,tag) VALUES ('1234','mechanical'),('1234','regional'),('1234','service') ON DUPLICATE KEY UPDATE client_id = '1234';
    

    ON DUPLICATE 部分很重要,因为出于某种原因,client_id 被设置为主键。我将不得不与应用程序人员交谈,看看这对他们是否重要。

    不幸的是,bind_param 没有被使用,但这是一个仅适用于公司员工的管理面板访问权限,现在它正在工作,我正在给他们自动完成框以引用现有值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-17
      • 1970-01-01
      相关资源
      最近更新 更多