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;
    	}
    }
    ?>