未定义的方法mysqli_stmt :: get_result()

时间:2013-01-24 20:22:49

标签: php mysqli

在我的服务器上我收到此错误

Fatal error: Call to undefined method mysqli_stmt::get_result() in /var/www/virtual/fcb/htdocs/library/mysqlidbclass.php on line 144

我有一个这样的包装:

<?php

/* https://github.com/aaron-lord/mysqli */

class mysqlidb {
    /**
     * Set up the database connection
     */

    public function __construct($server,$user,$password,$db){
        $this->connection = $this->connect($server, $user, $password, $db, true);
    }


    /**
     * Connect to the database, with or without a persistant connection
     * @param  String  $host       Mysql server hostname
     * @param  String  $user       Mysql username
     * @param  String  $pass       Mysql password
     * @param  String  $db         Database to use
     * @param  boolean $persistant Create a persistant connection
     * @return Object              Mysqli
     */
    private function connect($host, $user, $pass, $db, $persistant = true){
        $host = $persistant === true ? 'p:'.$host : $host;

        $mysqli = new mysqli($host, $user, $pass, $db);

        if($mysqli->connect_error)
            throw new Exception('Connection Error: '.$mysqli->connect_error);

        $mysqli->set_charset('utf8');

        return $mysqli;
    }

    /**
     * Execute an SQL statement for execution.
     * @param  String $sql An SQL query
     * @return Object      $this
     */
    public function query($sql){
        $this->num_rows = 0;
        $this->affected_rows = -1;

        if(is_object($this->connection)){
            $stmt = $this->connection->query($sql);

            # Affected rows has to go here for query :o
            $this->affected_rows = $this->connection->affected_rows;
            $this->stmt = $stmt;
            return $this;
        }
        else {
            throw new Exception;
        }
    }

    /**
     * Prepare an SQL statement
     * @param  String $sql An SQL query
     * @return Object      $this
     */
    public function prepare($sql){
        unset($this->stmt);
        $this->num_rows = 0;
        $this->affected_rows = -1;

        if(is_object($this->connection)){
            # Ready the stmt

            $this->stmt = $this->connection->prepare($sql);

            if (false===$this->stmt)
            {
                print('prepare failed: ' . htmlspecialchars($this->connection->error)."<br />");
            }

            return $this;
        }
        else {
            throw new Exception();
        }
    }

    public function multi_query(){ }

    /**
     * Escapes the arguments passed in and executes a prepared Query.
     * @param Mixed $var   The value to be bound to the first SQL ?
     * @param Mixed $...   Each subsequent value to be bound to ?
     * @return Object      $this
     */
    public function execute(){
        if(is_object($this->connection) && is_object($this->stmt)){
            # Ready the params
            if(count($args = func_get_args()) > 0){
                $types = array();
                $params = array();

                foreach($args as $arg){
                    $types[] = is_int($arg) ? 'i' : (is_float($arg) ? 'd' : 's');
                    $params[] = $arg;
                }

                # Stick the types at the start of the params
                array_unshift($params, implode($types));

                # Call bind_param (avoiding the pass_by_reference crap)
                call_user_func_array(
                    array($this->stmt, 'bind_param'),
                    $this->_pass_by_reference($params)
                );
            }

            if($this->stmt->execute()){
                # Affected rows to be run after execute for prepares
                $this->affected_rows = $this->stmt->affected_rows;
                return $this;
            }
            else {
                throw new Exception($this->connection->error);
            }
        }
        else {
            throw new Exception;
        }
    }

    /**
     * Fetch all results as an array, the type of array depend on the $method passed through.
     * @param  string  $method     Optional perameter to indicate what type of array to return.'assoc' is the default and returns an accociative array, 'row' returns a numeric array and 'array' returns an array of both.
     * @param  boolean $close_stmt Optional perameter to indicate if the statement should be destroyed after execution.
     * @return Array              Array of database results
     */
    public function results($method = 'assoc', $close_stmt = false){
        if(is_object($this->stmt)){
            $stmt_type = get_class($this->stmt);

            # Grab the result prepare() & query()
            switch($stmt_type){
                case 'mysqli_stmt':
                    $result = $this->stmt->get_result();
                    $close_result = 'close';
                    break;

                case 'mysqli_result':
                    $result = $this->stmt;
                    $close_result = 'free';
                    break;

                default:
                    throw new Exception;
            }

            $this->num_rows = $result->num_rows;

            # Set the results type
            switch($method) {
                case 'assoc':
                    $method = 'fetch_assoc';
                    break;

                case 'row':
                    //return 'fetch_row';
                    $method = 'fetch_row';
                    break;

                default:
                    $method = 'fetch_array';
                    break;
            }

            $results = array();
            while($row = $result->$method()){
                $results[] = $row;
            }

            $result->$close_result();
            return $results;
        }
        else {
            throw new Exception;
        }
    }

    /**
     * Turns off auto-committing database modifications, starting a new transaction.
     * @return bool Dependant on the how successful the autocommit() call was
     */
    public function start_transaction(){
        if(is_object($this->connection)){
            return $this->connection->autocommit(false);
        }
    }

    /**
     * Commits the current transaction and turns auto-committing database modifications on, ending transactions.
     * @return bool Dependant on the how successful the autocommit() call was
     */
    public function commit(){
        if(is_object($this->connection)){
            # Commit!
            if($this->connection->commit()){
                return $this->connection->autocommit(true);
            }
            else {
                $this->connection->autocommit(true);
                throw new Exception;
            }
        }
    }

    /**
     * Rolls back current transaction and turns auto-committing database modifications on, ending transactions.
     * @return bool Dependant on the how successful the autocommit() call was
     */
    public function rollback(){
        if(is_object($this->connection)){
            # Commit!
            if($this->connection->rollback()){
                return $this->connection->autocommit(true);
            }
            else {
                $this->connection->autocommit(true);
                throw new Exception;
            }
        }
    }

    /**
     * Return the number of rows in statements result set.
     * @return integer The number of rows
     */
    public function num_rows(){
        return $this->num_rows;
    }

    /**
     * Gets the number of affected rows in a previous MySQL operation.
     * @return integer The affected rows
     */
    public function affected_rows(){
        return $this->affected_rows;
    }

    /**
     * Returns the auto generated id used in the last query.
     * @return integer The last auto generated id
     */
    public function insert_id(){
        if(is_object($this->connection)){
            return $this->connection->insert_id;
        }
    }

    /**
     * Fixes the call_user_func_array & bind_param pass by reference crap.
     * @param  array $arr The array to be referenced
     * @return array      A referenced array
     */
    private function _pass_by_reference(&$arr){ 
        $refs = array(); 
        foreach($arr as $key => $value){
            $refs[$key] = &$arr[$key]; 
        }
        return $refs; 
    }
}

?>

有没有办法使用其他功能,以便我不必重写整个应用程序?请告诉我是否有。

2 个答案:

答案 0 :(得分:1)

请阅读此方法的用户说明:

http://php.net/manual/en/mysqli-stmt.get-result.php

它需要mysqlnd驱动程序。如果您的网站空间没有安装,则必须使用BIND_RESULT&amp; FETCH

http://www.php.net/manual/en/mysqli-stmt.bind-result.php

http://www.php.net/manual/en/mysqli-stmt.fetch.php

摘自here

答案 1 :(得分:0)

此错误的原因是您的服务器没有安装mysqlnd驱动程序驱动程序。 (请参阅here。)如果您拥有管理员权限,则可以自行安装,但也有更简单的方法:

我编写了两个简单的函数,它们提供与$stmt->get_result();相同的功能,但它们不需要mysqlnd驱动程序。

您只需替换

$result = $stmt->get_result(); $fields = bindAll($stmt);

$row= $stmt->get_result(); $row = fetchRowAssoc($stmt, $fields);

(要获取返回的行数,可以使用$stmt->num_rows。)

你只需要放置这两个函数我已经在PHP脚本的某处编写了。 (例如在底部)

function bindAll($stmt) {
    $meta = $stmt->result_metadata();
    $fields = array();
    $fieldRefs = array();
    while ($field = $meta->fetch_field())
    {
        $fields[$field->name] = "";
        $fieldRefs[] = &$fields[$field->name];
    }

    call_user_func_array(array($stmt, 'bind_result'), $fieldRefs);
    $stmt->store_result();
    //var_dump($fields);
    return $fields;
}

function fetchRowAssoc($stmt, &$fields) {
    if ($stmt->fetch()) {
        return $fields;
    }
    return false;
}

工作原理

我的代码使用$stmt->result_metadata();函数来确定返回了多少和哪些字段,然后自动将获取的结果绑定到预先创建的引用。像魅力一样工作!

同时发布了here