【问题标题】:PHP prepared statement within a prepared statement准备好的语句中的 PHP 准备好的语句
【发布时间】:2011-04-07 10:22:34
【问题描述】:

我正在浏览有关使用 db 制作菜单的视频教程。我没有像视频中那样使用程序 PHP 来做,而是尝试用准备好的语句 OOP 风格来做。它不起作用,我不知道为什么。

它运行良好,直到第 17 行,它死于此错误:

Fatal error: Call to a member function bind_param() on a non-object in C:\wamp\www\widget_corp\content.php on line 17

这是代码:

    <?php
        $query = $connection->prepare('SELECT menu_name, id FROM subjects ORDER BY position ASC;');
        $query->execute();
        $query->bind_result($menu_name, $sid);

        while ($query->fetch()){
            echo "<li>{$menu_name} {$sid}</li>";

            $query2 = $connection->prepare('SELECT menu_name FROM pages WHERE subject_id = ? ORDER BY position ASC;');
            $query2->bind_param("i", $sid); //This is line 17
            $query2->execute();
            $query2->bind_result($menu_name);
            echo "<ul class='pages'>";              
            while ($query2->fetch()){
                echo "<li>{$menu_name}</li>";
            }
            echo "</ul>";

        }
        $query->close();
    ?>

在stmt->fetch();里面做prepared statement是不可能的吗?

【问题讨论】:

  • 您使用的是 mysqli 扩展,对吧?您是否考虑过使用 PDO 代替?使用 PDO,您可以将异常作为“错误处理程序”,这使您更难错过 sql 错误(在这种情况下,最有可能是由第 16 行引起的错误;-))
  • 是的,是mysqli,但不是sql错误。在终端中运行 SQL 查询,运行良好。

标签: php mysql prepared-statement


【解决方案1】:

想通了:

在执行和绑定结果之后,它必须被存储(如果另一个准备好的语句被放入 fetch 中)。因此,这种情况下的获取必须从缓冲结果中读取。

换句话说,在对同一连接进行提取之前,无法执行另一个查询。

工作代码:

$query = $connection->prepare("SELECT menu_name, id FROM subjects ORDER BY position ASC;");
$query->execute();
$query->bind_result($menu_name, $sid);
$query->store_result();

【讨论】:

  • "...它必须被存储".. 救生员!
【解决方案2】:
$stmt = mysqli_prepare($con,"SELECT menu_name, id FROM subjects ORDER BY position ASC");
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $menu_name, $id);
while (mysqli_stmt_fetch($stmt))
{
 $stmt2 = mysqli_prepare($con2,"SELECT menu_name FROM pages WHERE subject_id = ? ORDER BY position ASC;");
 mysqli_stmt_bind_param($stmt2,$id);
 mysqli_stmt_execute($stmt2);
 mysqli_stmt_bind_result($stmt2, $name);
 while (mysqli_stmt_fetch($stmt2))
  echo $name;
}

看看$con和$con2,你不能在另一个ps中使用相同的连接执行prepare语句!!!

【讨论】:

  • 在这种情况下不需要存储结果,所以你可以节省内存和时间:)
【解决方案3】:

是的,你可以有多个prepared statements:prepared statements的思想之一是“prepare once, execute many times”。

  • 因此,您应该在循环之外准备语句——因此它只准备一次
  • 并在循环内部多次执行它。


您收到的致命错误意味着第 17 行的 $query2 不是对象——这意味着 prepare 失败。

prepare 通常会在其中出现错误时失败;你确定你的查询有效吗?表名和列名可以吗?

prepare 失败时,您应该能够收到错误消息,使用mysqli-&gt;error() -- 或PDO::errorInfo()

【讨论】:

  • 如果我把它从循环中取出,查询就可以正常工作。而“i”代表整数,因此它知道用整数代替?。它不受名称的约束。
  • 哼,对不起,我忘记了它是如何工作的 :-( 我已经删除了这部分答案...您是否尝试收到由准备引起的错误消息?
  • 如果我把里面的准备放在外面,我什么都不做。没有错误也没有结果。除了准备的原始错误消息之外,我无法收到任何其他错误消息。 (顺便说一句,您的响应时间非常快,我非常感谢您)
  • 哼,真奇怪;也许其他人会有一个想法...... (好吧,我也不总是这样 - 但当我这样做时,我有时会回答:-))
【解决方案4】:

您没有说您正在使用什么数据库扩展,但您似乎没有测试您正在使用的任何函数的返回值。您不能假设 DB 调用将始终完美运行。

【讨论】:

    最近更新 更多