【问题标题】:PDO Prepared Statement not returning resultsPDO Prepared Statement 未返回结果
【发布时间】:2014-02-24 20:46:41
【问题描述】:

我整天都在尝试使用 mysqli 的准备好的语句来进行概念验证,但后来决定使用 PDO,因为它具有绑定值的能力——我相信我需要它们,因为它的动态性质我的查询。

幕后的形式是这样的:http://pasteboard.co/k6H0cVq.png - 你也可以在这里了解这个概念。我的查询没有返回任何结果或错误,只是一个警告Array to string conversion - 在绑定值时发生。

我还担心我的值绑定不起作用,我不能将它们放在 foreach 循环中,因为它不能位于调用 $stmt 变量之前,否则会引发更多错误出去。

我一直在阅读文档和观看教程,但我找不到任何说明如何在查询是动态的情况下实现模型的内容。

我希望我足够清楚,试图了解 PDO 和准备好的陈述是一项令人沮丧的努力。

非常感谢任何帮助。 谢谢!

PHP

if (isset($_POST['platform'], $_POST['bandwidth'], $_POST['price'])){

    $platform = $_POST['platform'];
    $bandwidth = $_POST['bandwidth'];
    $price = $_POST['price'];
    $query = "SELECT * FROM 'hosts' WHERE";

    foreach($platform as $platform) {
        $query .= " 'platform' LIKE %:platform% OR";
    }   
    $query = substr($query, 0, -2); 

    foreach($bandwidth as $bandwidth) {
        $query .= " AND 'bandwidth' BETWEEN :bandwidth OR";
    }   
    $query = substr($query, 0, -2); 

    foreach($price as $price) {
        $query .= " AND 'price' BETWEEN :price OR";
    }   
    $query = substr($query, 0, -2); 

    $conn =  new PDO('mysql:host=127.0.0.1; dbname=test', 'root', '');
    $stmt = $conn->prepare($query);

    if ($_POST['platform']){
        $stmt->bindValue(':platform', $_POST['platform']);  
    }

    if ($_POST['bandwidth']){
        $stmt->bindValue(':bandwidth', $_POST['bandwidth']);    
    }   

    if ($_POST['price']){
        $stmt->bindValue(':price', $_POST['price']);    
    }   

    $stmt->execute();

    foreach($stmt as $row) {
        print_r($row); 
    }
}

【问题讨论】:

  • 您不能多次使用同一个命名占位符。您不能将数组绑定到占位符。如果你有占位符,它们需要被绑定——所以不要有条件地绑定。没有像BETWEEN ... OR ... 这样的运算符。您应该在foreach() 语句中为赋值使用一个变量名,该变量名与它所迭代的数组的名称不同。您应该激活将导致显示错误信息的 PDO 错误模式,或者显式测试错误条件。这应该足以让您入门。
  • 谢谢。当您谈论占位符时,是否与以下内容有关: 'bandwidth' BETWEEN :bandwidth OR foreach ($price as $price)
  • 您在查询中的列名周围使用了错误类型的引号,它们应该是反引号,而不是单引号。
  • 您还需要关注ANDOR 的优先级,您可能需要在所有OR 组周围加上括号。
  • 你不能写LIKE %:platform%,因为LIKE的参数必须是一个字符串。应该是LIKE CONCAT('%', :platform, '%')

标签: php mysql database pdo prepared-statement


【解决方案1】:

恐怕您无法像尝试那样迭代该语句。而是使用fetch 方法来访问查询结果:

while ($row = $stmt->fetch([fetch mode, e.g., PDO::FETCH_ASSOC])) {
    print_r($row);
}

关于您得到的“数组到字符串转换”错误,我怀疑一个或多个 POST 变量实际上是一个数组。要检验这个假设,请尝试 print_r($_POST)。

【讨论】:

  • 另外,我知道它们是数组,如果你看一下链接中的图像,选择框允许多个选项,因此返回一个数组。
  • 我认为您的意思是输入: while ($row = $stmt->fetch( PDO::FETCH_ASSOC )) - 对我来说,它不会返回错误。但仍然没有解决手头的更大问题。 :-(
  • -1 这个答案离题太远了。 PDOStatement 实现了 Traversable,因此绝对可以像 OP 最初所做的那样使用 foreach() 对其进行迭代。此外,此答案完全无法识别 OP 代码的任何其他(严重)问题。
  • @eggyal 我不知道 PDOStatement 实现 Traversable 并欣赏这些信息。话虽如此,您的评论很粗鲁,因此不合适。
【解决方案2】:

这是对您的代码的重写。我使用数组来构建嵌套的ANDOR 条件,使用implode 组合它们,而不是字符串连接序列。我使用数组索引给每个占位符一个不同的名称。我将您所有的 BETWEEN 子句更改为 =,因为 BETWEEN 需要两个参数,范围的开头和结尾。

if (isset($_POST['platform'], $_POST['bandwidth'], $_POST['price'])){

    $platform = $_POST['platform'];
    $bandwidth = $_POST['bandwidth'];
    $price = $_POST['price'];
    $query = "SELECT * FROM hosts";

    $ands = array();
    $bind_array = array();

    $ors = array();
    foreach($platform as $i => $platform) {
        $ors[] = "platform LIKE CONCAT('%', :platform{$i}, '%')";
        $bind_array[":platform{$i}"] = $platform;
    }   
    if ($ors) {
        $ands[] = "(" . implode(" OR ", $ors) . ")";
    }

    $ors = array();
    foreach($bandwidth as $i => $bandwidth) {
        $ors[] = "bandwidth = :bandwidth{$i}";
        $bind_array[":bandwidth{$i}"] = $bandwidth;
    }   
    if ($ors) {
        $ands[] = "(" . implode(" OR ", $ors) . ")";
    }

    $ors = array();
    foreach($price as $i => $price) {
        $ors[] = "price = :price{$i}";
        $bind_array[":price{$i}"] = $price;
    }

    if ($ors) {
        $ands[] = "(" . implode(" OR ", $ors) . ")";
    }
    if ($ands) {
        $query .= " WHERE " . implode(" AND ", $ands);
    }

    $conn =  new PDO('mysql:host=127.0.0.1; dbname=test', 'root', '');
    $stmt = $conn->prepare($query);

    $stmt->execute($bind_array);

    foreach ($stmt as $row) {
        print_r($row); 
    }
}

更新:

如果一个范围有两个参数 price1[]price2[],请将 price 循环更改为:

    foreach($price1 as $i => $price) {
        $ors[] = "price BETWEEN :pricelow{$i} AND :pricehigh{$i}";
        $bind_array[":pricelow{$i}"] = $price;
        $bind_array[":pricehigh{$i}"] = $price2[$i];
    }

【讨论】:

  • 我欠你 BIG 时间,谢谢朋友!我会在早上试试这个(我来自英国)。
  • 小问题 - 解析错误:语法错误,第 81 行出现意外的“as”(T_AS)。但是,第 81 行 - 在记事本中不包含“as”。知道为什么会这样吗?
  • 我必须尝试一下,我等不及了。哈哈。
  • 好问题!它是:while($stmt as $row) {
  • 应该是foreach。我开始将其更改为while,然后不完全地撤消它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-24
  • 1970-01-01
  • 1970-01-01
  • 2021-08-03
  • 1970-01-01
  • 2014-12-17
  • 1970-01-01
相关资源
最近更新 更多