Skip to main content
2 of 3
added 61 characters in body
steveo225
  • 258
  • 2
  • 9

mysqli wrapper class

I made the following class to wrap mysqli for PHP using prepared statements. It seems to work well, but I was hoping to get opinions (on overall structure, performance, usage, etc.). Thanks for the insight.

<?php
class database {
    private $conn, $stmt, $arr, $eof=true, $error;

    public function __construct($host, $user, $pass, $db) {
        $this->conn = mysqli_connect($host, $user, $pass, $db);
        if(mysqli_connect_errno()) $this->error = mysqli_connect_error();
    }

    public function __destruct() {
        if($this->stmt) mysqli_stmt_close($this->stmt);
        mysqli_close($this->conn);
    }

    // returns false on error, true on successful select, number of affected rows otherwise
    // at minimum, query is the sql statement to execute
    // if there are query parameters, the second argument is is the types list, followed by the parameters
    // e.g. query('SELECT * FROM table WHERE id = ?', 'i', 5)
    public function query($query) {
        // create a new prepared statement
        $stmt = mysqli_prepare($this->conn, $query);
        if(!$stmt) {
            $this->error = mysqli_error($this->conn);
            return false;
        }

        // apply the arguments if any exist
        if(func_num_args() > 2) {
            $args = array_slice(func_get_args(), 1);
            $refs = array();
            foreach($args as $key=>&$value) $refs[$key] = &$value;
            call_user_func_array(array($stmt, 'bind_param'), $refs);
        }

        // run the query
        $stmt->execute();
        if($stmt->errno) {
            $this->error = mysqli_error($this->conn);
            return false;
        }

        // if the query was not a select, return the number of rows affected
        if($stmt->affected_rows > -1) {
            $rows = $stmt->affected_rows;
            mysqli_stmt_close($stmt);
            return $rows;
        }

        // close any previous statement
        if($this->stmt) mysqli_stmt_close($this->stmt);
        $this->stmt = $stmt;
        $this->eof = false;

        // bind the results to the associative array
        $this->arr = array();
        $refs = array();
        $meta = mysqli_stmt_result_metadata($stmt);
        while($column = mysqli_fetch_field($meta)) {
            $refs[] = &$this->arr[str_replace(' ', '_', $column->name)];
        }
        call_user_func_array(array($stmt, 'bind_result'), $refs);

        // make the first result set available
        $this->next();
        return true;
    }

    // fetches the next row
    public function next() {
        if($this->stmt) {
            $ret = mysqli_stmt_fetch($this->stmt); // populates $this->arr
            $this->eof = ($ret !== true);
            if($ret === false) $this->error = mysqli_error($this->conn);
        }
    }

    // returns an associative array of the results
    public function results() {
        // must make a copy when returning the entire array because
        // the array holds references that may be updated
        $ret = array();
        foreach($this->arr as $key=>$value) $ret[$key] = $value;
        return $ret;
    }

    // return the value for the specified field
    public function result($field) { return $this->arr[$field]; }
    public function __get($field) { return $this->result($field); }

    // returns true if eof has occured or an error
    public function eof() { return $this->eof; }

    // returns the number of rows in the result set
    public function count() { return ($this->stmt ? $this->stmt->num_rows : 0); }

    // returns the last error message, if clear is true, clears the error as well
    public function error($clear=false) {
        $err = $this->error;
        if($clear) $this->error = '';
        return $err;
    }
}
?>
steveo225
  • 258
  • 2
  • 9