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