PHP Commands out of sync; you can't run this command now

允我心安 提交于 2021-02-10 23:42:19

问题


I've seen this question before but all the solutions do not work for me. The main solution is to store the result which I already do. Most people say I am running 2 simultaneous queries which I don't understand. I may have used this function below more than once but I always free and close the statement so not sure why this is happening.

You can most likely ignore the top half of the function which just generates a string to represent the types. This is the full DB class I made:

(I edited it since I originally posted it and replaced self::$connection with 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();
    }
}

EDIT: This is what one of my requests looks like (I have queried 2 requests on this same page using my DB class and DB::query(...) function):

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

回答1:


For the love of what is sane, change your driver to PDO and make all this code into

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

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

to be used like this

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



回答2:


The MySQL documentation regarding Commands out of sync suggest two possibilities:

  1. You have used a result and are trying to execute a new query before freeing the last result.
  2. You are running two queries (not necessarily simultaneously) without using or storing the result between each one.

The logic in your code shows the only situation where you are not freeing results is when no prepared statement is required. The answer to your problem may be to deal with this particular result and free or store it.

I can see from your code self::$connection is a static reference, therefore it could be possible that any query executed in that scope is using the same connection. It is hard to tell without being able to see your full class.



来源:https://stackoverflow.com/questions/35536580/php-commands-out-of-sync-you-cant-run-this-command-now

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!