【问题标题】:PHP Commands out of sync; you can't run this command nowPHP 命令不同步;你现在不能运行这个命令
【发布时间】:2016-02-21 13:14:09
【问题描述】:

我以前见过这个问题,但所有的解决方案都不适合我。主要的解决方案是存储我已经做的结果。大多数人说我正在运行 2 个我不理解的同时查询。我可能不止一次使用下面的这个函数,但我总是释放并关闭语句,所以不知道为什么会发生这种情况。

您很可能会忽略函数的上半部分,它只生成一个字符串来表示类型。这是我制作的完整 DB 类:

(我在最初发布它后对其进行了编辑,并将 self::$connection 替换为 self::$db)

class DB {
    private static $dbhost = "localhost";
    private static $dbuser = "some_user"; // placeholder
    private static $dbpass = "some_assword"; // placeholder
    private static $dbname = "database_name"; // placeholder
    private static $db;

    public static function connect() {          
        self::$db = new mysqli(self::$dbhost,  self::$dbuser, self::$dbpass, self::$dbname);        
        if (self::$db->connect_errno) {
            die("Database mysqli failed: " .
                self::$db->connect_error . " (" . 
                self::$db->connect_errno . ")"      
            );
        }
    }

    // IGNORE THIS! It just formats the parameters for the 
    // call_user_func_array function to work correctly.
    private static function getBindings(&$params) {
        $types = "";        
        $bindings = array();
        foreach ($params as $value) {
            switch (gettype($value)) {
                case "integer":
                    $types .= "i";
                    break;
                case "double":
                    $types .= "d";
                    break;
                case "string":
                    $types .= "s";
                    break;
                default: 
                    $types .= "s";
                    break;
            }
        }       
        foreach($params as $key => $value)
            $bindings[$key] = &$params[$key]; // assign to references (because bind_param requires references)      
        // to add a string of variable types to the start of the $bindings array (such as 'sss')
        array_unshift($bindings, $types);
        return $bindings;
    }

    public static function query($query, $params) {
        if (!isset(self::$db)) { self::connect(); }

        if (empty($params)) {
            // prepared statement not needed
            return self::$db->query($query);
        }

        $successful = false;
        $bindings = self::getBindings($params);

        // MySQL prepared statement execution:
        $statement = self::$db->prepare($query);
        call_user_func_array(array($statement, 'bind_param'), $bindings);       
        $statement->execute();
        $statement->store_result(); 

        if ($statement->num_rows > 0) {
            // for select queries
            $successful = $statement->get_result(); // does not work! (returns boolean)

            echo self::$db->errno; // 2014          
            echo "<br />";
            echo self::$db->error; // Commands out of sync; you can't run this command now
            echo "<br />";      

            // this method works fine (but I need to return the result set!):
            /*$name = false; $link = false;
            $statement->bind_result($name, $link);

           while ($statement->fetch()) {
                echo 'name: '.$name.'<br>';
                echo 'link: '.$link.'<br>';
           }*/
        } else if ($statement->affected_rows > 0) {
            // for insert queries
            $successful = true;
        }       

        $statement->free_result();
        $statement->close();
        return $successful;
    }

    public static function close() {
        if (isset(self::$db)) self::$db->close();
    }
}

编辑:这是我的一个请求的样子(我已经使用我的 DB 类和 DB::query(...) 函数在同一页面上查询了 2 个请求):

$result = DB::query("SELECT * FROM table_name;");
if ($result) {
    while ($row = $result->fetch_assoc()) {
        // do stuff                             
    }
    $result->close();
}

【问题讨论】:

  • 这是否与您同时使用store_resultget_result 的事实有关?
  • @ethrbunny 不,我不这么认为。文档说您需要先存储它,然后 get_result 只检索存储的内容。
  • mysqli - get_result - "调用以从准备好的语句查询返回结果集"
  • 是的,但除非您先存储它,否则它不会返回任何内容。 store_result 说:“您必须为每个成功生成结果集的查询调用 mysqli_stmt_store_result()”和“从准备好的语句中传输结果集”。 store_result 只返回一个布尔值来标记它是否成功,而不是一个结果集。

标签: php mysqli


【解决方案1】:

出于对理智的热爱,将您的驱动程序更改为 PDO 并将所有这些代码放入

public static function query($query, $params = NULL)
{
    if (!$params) {
        return self::$connection->query($query);
    }

    $statement = self::$connection->prepare($query);
    $statement->execute($params);
    return $statement;
}

这样使用

$result = DB::query("SELECT * FROM table_name");
foreach($result as  $row) {
    // do stuff                             
}

【讨论】:

  • 这可能会有所帮助。还在学习 PHP,所以从来没有研究过 PDO,我最好学习一下:S
  • 很好,但你能解释一下为什么这会解决问题以及他们做错了什么吗?
  • @HenryTK 绝对不会是 mysqli 只是为每个人都安装了窃听器。我正在关闭并按照您的设想释放结果,但不知道为什么会发生这种情况。
【解决方案2】:

关于 Commands out of sync 的 MySQL 文档提出了两种可能性:

  1. 您已经使用了一个结果,并试图在释放最后一个结果之前执行一个新查询。
  2. 您正在运行两个查询(不一定同时),但没有使用或存储每个查询之间的结果。

您的代码中的逻辑显示了您不释放结果的唯一情况是不需要准备好的语句。您的问题的答案可能是处理此特定结果并将其释放或存储。

我可以从您的代码中看到self::$connection 是一个静态引用,因此在该范围内执行的任何查询都可能使用相同的连接。如果不能看到你的全班,很难说。

【讨论】:

  • 是的,我只使用一次连接到数据库: self::$connection = mysqli_connect(self::$dbhost, //self::$dbuser, self::$dbpass, self:: $数据库名);但我以为你只需要连接一次就可以执行许多查询然后关闭它?
  • 正确,您可以使用相同的连接执行多个查询。我有一个理论,你正在做的一个查询可能不是一个准备好的语句,因为你在那个时候返回,因此可能会留下一个结果集而不存储或释放它。您使用该连接运行了多少个查询,它们是什么?
  • 我在 PHP 页面中使用了 2 个查询并使用 $result->free() ,这没有什么区别。我也试过 $result->close() 和相同的结果。如果我同时使用它们,则会出现错误。
  • 谁对我的回答投了反对票,请解释原因。我喜欢真正从错误中学习,这是最好的学习方式之一。
  • 不是我,只是为了记录。
猜你喜欢
  • 2013-10-05
  • 2016-04-11
  • 1970-01-01
  • 2016-05-28
  • 2015-04-16
  • 1970-01-01
  • 1970-01-01
  • 2013-04-08
  • 2021-10-13
相关资源
最近更新 更多