Commit 5f443c88 authored by Josh Campbell's avatar Josh Campbell

Merge pull request #7 from Gemorroj/master

code review (psr1/psr2, charset)
parents 2a19a70c d5e2a79c
<?php <?php
/** /**
* MySqliDb Class * MysqliDb Class
* *
* @category Database Access * @category Database Access
* @package MysqliDB * @package MysqliDb
* @author Jeffery Way <jeffrey@jeffrey-way.com> * @author Jeffery Way <jeffrey@jeffrey-way.com>
* @author Josh Campbell <jcampbell@ajillion.com> * @author Josh Campbell <jcampbell@ajillion.com>
* @copyright Copyright (c) 2010 * @copyright Copyright (c) 2010
* @license http://opensource.org/licenses/gpl-3.0.html GNU Public License * @license http://opensource.org/licenses/gpl-3.0.html GNU Public License
* @version 1.1 * @version 1.1
**/ **/
class MysqliDB { class MysqliDb
{
/** /**
* Static instance of self * Static instance of self
* *
* @var object * @var MysqliDb
*/ */
protected static $_instance; protected static $_instance;
/** /**
* MySQLi instance * MySQLi instance
* *
* @var object * @var mysqli
*/ */
protected $_mysqli; protected $_mysqli;
/** /**
* The SQL query to be prepared and executed * The SQL query to be prepared and executed
* *
* @var object * @var string
*/ */
protected $_query; protected $_query;
/** /**
* An array that holds where conditions 'fieldname' => 'value' * An array that holds where conditions 'fieldname' => 'value'
* *
* @var array * @var array
*/ */
protected $_where = array(); protected $_where = array();
/** /**
* Dynamic type list for where condition values * Dynamic type list for where condition values
* *
* @var array * @var array
*/ */
protected $_whereTypeList; protected $_whereTypeList;
/** /**
* Dynamic type list for table data values * Dynamic type list for table data values
* *
* @var array * @var array
*/ */
protected $_paramTypeList; protected $_paramTypeList;
/** /**
* Dynamic array that holds a combination of where condition/table data value types and parameter referances * Dynamic array that holds a combination of where condition/table data value types and parameter referances
* *
* @var array * @var array
*/ */
protected $_bindParams = array(''); // Create the empty 0 index protected $_bindParams = array(''); // Create the empty 0 index
public function __construct($host, $username, $password, $db) { /**
$this->_mysqli = new mysqli($host, $username, $password, $db) * @param string $host
or die('There was a problem connecting to the database'); * @param string $username
self::$_instance = $this; * @param string $password
} * @param string $db
*/
/** public function __construct($host, $username, $password, $db)
* A method of returning the static instance to allow access to the {
* instantiated object from within another class. $this->_mysqli = new mysqli($host, $username, $password, $db)
* Inheriting this class would require reloading connection info. or die('There was a problem connecting to the database');
*
* @uses $db = MySqliDb::getInstance(); $this->_mysqli->set_charset('utf8');
*
* @return object Returns the current instance. self::$_instance = $this;
*/ }
public static function getInstance()
{ /**
return self::$_instance; * A method of returning the static instance to allow access to the
} * instantiated object from within another class.
* Inheriting this class would require reloading connection info.
/** *
* Reset states after an execution * @uses $db = MySqliDb::getInstance();
* *
* @return object Returns the current instance. * @return object Returns the current instance.
*/ */
protected function reset() public static function getInstance()
{ {
$this->_where = array(); return self::$_instance;
$this->_bindParams = array(''); // Create the empty 0 index }
unset($this->_query);
unset($this->_whereTypeList); /**
unset($this->_paramTypeList); * Reset states after an execution
} *
* @return object Returns the current instance.
/** */
* Pass in a raw query and an array containing the parameters to bind to the prepaird statement. protected function reset()
* {
* @param string $query Contains a user-provided query. $this->_where = array();
* @param array $bindData All variables to bind to the SQL statment. $this->_bindParams = array(''); // Create the empty 0 index
* @return array Contains the returned rows from the query. unset($this->_query);
*/ unset($this->_whereTypeList);
public function rawQuery($query, $bindParams = NULL) unset($this->_paramTypeList);
{ }
$this->_query = filter_var($query, FILTER_SANITIZE_STRING);
$stmt = $this->_prepareQuery(); /**
* Pass in a raw query and an array containing the parameters to bind to the prepaird statement.
if (gettype($bindParams) === 'array') { *
$params = array(''); // Create the empty 0 index * @param string $query Contains a user-provided query.
foreach ($bindParams as $prop => $val) { * @param array $bindParams All variables to bind to the SQL statment.
$params[0] .= $this->_determineType($val); *
array_push($params, $bindParams[$prop]); * @return array Contains the returned rows from the query.
} */
public function rawQuery($query, $bindParams = null)
call_user_func_array(array($stmt, "bind_param"),$this->refValues($params)); {
$this->_query = filter_var($query, FILTER_SANITIZE_STRING);
} $stmt = $this->_prepareQuery();
$stmt->execute(); if (is_array($bindParams) === true) {
$this->reset(); $params = array(''); // Create the empty 0 index
foreach ($bindParams as $prop => $val) {
$results = $this->_dynamicBindResults($stmt); $params[0] .= $this->_determineType($val);
return $results; array_push($params, $bindParams[$prop]);
} }
/** call_user_func_array(array($stmt, 'bind_param'), $this->refValues($params));
*
* @param string $query Contains a user-provided select query. }
* @param int $numRows The number of rows total to return.
* @return array Contains the returned rows from the query. $stmt->execute();
*/ $this->reset();
public function query($query, $numRows = NULL)
{ return $this->_dynamicBindResults($stmt);
$this->_query = filter_var($query, FILTER_SANITIZE_STRING); }
$stmt = $this->_buildQuery($numRows);
$stmt->execute(); /**
$this->reset(); *
* @param string $query Contains a user-provided select query.
$results = $this->_dynamicBindResults($stmt); * @param int $numRows The number of rows total to return.
return $results; *
} * @return array Contains the returned rows from the query.
*/
/** public function query($query, $numRows = null)
* A convenient SELECT * function. {
* $this->_query = filter_var($query, FILTER_SANITIZE_STRING);
* @param string $tableName The name of the database table to work with. $stmt = $this->_buildQuery($numRows);
* @param integer $numRows The number of rows total to return. $stmt->execute();
* @return array Contains the returned rows from the select query. $this->reset();
*/
public function get($tableName, $numRows = NULL) return $this->_dynamicBindResults($stmt);
{ }
$this->_query = "SELECT * FROM $tableName"; /**
$stmt = $this->_buildQuery($numRows); * A convenient SELECT * function.
$stmt->execute(); *
$this->reset(); * @param string $tableName The name of the database table to work with.
* @param integer $numRows The number of rows total to return.
$results = $this->_dynamicBindResults($stmt); *
return $results; * @return array Contains the returned rows from the select query.
} */
public function get($tableName, $numRows = null)
/** {
* $this->_query = "SELECT * FROM $tableName";
* @param <string $tableName The name of the table. $stmt = $this->_buildQuery($numRows);
* @param array $insertData Data containing information for inserting into the DB. $stmt->execute();
* @return boolean Boolean indicating whether the insert query was completed succesfully. $this->reset();
*/
public function insert($tableName, $insertData) return $this->_dynamicBindResults($stmt);
{ }
$this->_query = "INSERT into $tableName";
$stmt = $this->_buildQuery(NULL, $insertData); /**
$stmt->execute(); *
$this->reset(); * @param <string $tableName The name of the table.
* @param array $insertData Data containing information for inserting into the DB.
($stmt->affected_rows) ? $result = $stmt->insert_id : $result = false; *
return $result; * @return boolean Boolean indicating whether the insert query was completed succesfully.
} */
public function insert($tableName, $insertData)
/** {
* Update query. Be sure to first call the "where" method. $this->_query = "INSERT into $tableName";
* $stmt = $this->_buildQuery(null, $insertData);
* @param string $tableName The name of the database table to work with. $stmt->execute();
* @param array $tableData Array of data to update the desired row. $this->reset();
* @return boolean
*/ return ($stmt->affected_rows > 0 ? $stmt->insert_id : false);
public function update($tableName, $tableData) }
{
$this->_query = "UPDATE $tableName SET "; /**
* Update query. Be sure to first call the "where" method.
$stmt = $this->_buildQuery(NULL, $tableData); *
$stmt->execute(); * @param string $tableName The name of the database table to work with.
$this->reset(); * @param array $tableData Array of data to update the desired row.
*
($stmt->affected_rows) ? $result = true : $result = false; * @return boolean
return $result; */
} public function update($tableName, $tableData)
{
/** $this->_query = "UPDATE $tableName SET ";
* Delete query. Call the "where" method first.
* $stmt = $this->_buildQuery(null, $tableData);
* @param string $tableName The name of the database table to work with. $stmt->execute();
* @param integer $numRows The number of rows to delete. $this->reset();
* @return boolean Indicates success. 0 or 1.
*/ return ($stmt->affected_rows > 0);
public function delete($tableName, $numRows = NULL) { }
$this->_query = "DELETE FROM $tableName";
/**
$stmt = $this->_buildQuery($numRows); * Delete query. Call the "where" method first.
$stmt->execute(); *
$this->reset(); * @param string $tableName The name of the database table to work with.
* @param integer $numRows The number of rows to delete.
($stmt->affected_rows) ? $result = true : $result = false; *
return $result; * @return boolean Indicates success. 0 or 1.
} */
public function delete($tableName, $numRows = null)
/** {
* This method allows you to specify multipl (method chaining optional) WHERE statements for SQL queries. $this->_query = "DELETE FROM $tableName";
*
* @uses $MySqliDb->where('id', 7)->where('title', 'MyTitle'); $stmt = $this->_buildQuery($numRows);
* $stmt->execute();
* @param string $whereProp The name of the database field. $this->reset();
* @param mixed $whereValue The value of the database field.
*/ return ($stmt->affected_rows > 0);
public function where($whereProp, $whereValue) }
{
$this->_where[$whereProp] = $whereValue; /**
return $this; * This method allows you to specify multipl (method chaining optional) WHERE statements for SQL queries.
} *
* @uses $MySqliDb->where('id', 7)->where('title', 'MyTitle');
*
/** * @param string $whereProp The name of the database field.
* This methods returns the ID of the last inserted item * @param mixed $whereValue The value of the database field.
* *
* @return integer The last inserted item ID. * @return MysqliDb
*/ */
public function getInsertId() public function where($whereProp, $whereValue)
{ {
return $this->_mysqli->insert_id; $this->_where[$whereProp] = $whereValue;
} return $this;
}
/**
* Escape harmful characters which might affect a query.
* /**
* @param string $str The string to escape. * This methods returns the ID of the last inserted item
* @return string The escaped string. *
*/ * @return integer The last inserted item ID.
public function escape ( $str ) */
{ public function getInsertId()
return $this->_mysqli->real_escape_string ( $str ); {
} return $this->_mysqli->insert_id;
}
/**
* This method is needed for prepared statements. They require /**
* the data type of the field to be bound with "i" s", etc. * Escape harmful characters which might affect a query.
* This function takes the input, determines what type it is, *
* and then updates the param_type. * @param string $str The string to escape.
* *
* @param mixed $item Input to determine the type. * @return string The escaped string.
* @return string The joined parameter types. */
*/ public function escape($str)
protected function _determineType($item) {
{ return $this->_mysqli->real_escape_string($str);
switch (gettype($item)) { }
case 'NULL':
case 'string': /**
return 's'; * This method is needed for prepared statements. They require
break; * the data type of the field to be bound with "i" s", etc.
* This function takes the input, determines what type it is,
case 'integer': * and then updates the param_type.
return 'i'; *
break; * @param mixed $item Input to determine the type.
*
case 'blob': * @return string The joined parameter types.
return 'b'; */
break; protected function _determineType($item)
{
case 'double': switch (gettype($item)) {
return 'd'; case 'NULL':
break; case 'string':
} return 's';
} break;
/** case 'integer':
* Abstraction method that will compile the WHERE statement, return 'i';
* any passed update data, and the desired rows. break;
* It then builds the SQL query.
* case 'blob':
* @param int $numRows The number of rows total to return. return 'b';
* @param array $tableData Should contain an array of data for updating the database. break;
* @return object Returns the $stmt object.
*/ case 'double':
protected function _buildQuery($numRows = NULL, $tableData = NULL) return 'd';
{ break;
(gettype($tableData) === 'array') ? $hasTableData = true : $hasTableData = false; }
(!empty($this->_where )) ? $hasConditional = true : $hasConditional = false; return '';
}
// Did the user call the "where" method?
if (!empty($this->_where)) { /**
* Abstraction method that will compile the WHERE statement,
// if update data was passed, filter through and create the SQL query, accordingly. * any passed update data, and the desired rows.
if ($hasTableData) { * It then builds the SQL query.
$i = 1; *
$pos = strpos($this->_query, 'UPDATE'); * @param int $numRows The number of rows total to return.
if ( $pos !== false) { * @param array $tableData Should contain an array of data for updating the database.
foreach ($tableData as $prop => $value) { *
// determines what data type the item is, for binding purposes. * @return mysqli_stmt Returns the $stmt object.
$this->_paramTypeList .= $this->_determineType($value); */
protected function _buildQuery($numRows = null, $tableData = null)
// prepares the reset of the SQL query. {
($i === count($tableData)) ? $hasTableData = is_array($tableData);
$this->_query .= $prop . ' = ?': $hasConditional = !empty($this->_where);
$this->_query .= $prop . ' = ?, ';
// Did the user call the "where" method?
$i++; if (!empty($this->_where)) {
}
} // if update data was passed, filter through and create the SQL query, accordingly.
} if ($hasTableData) {
$pos = strpos($this->_query, 'UPDATE');
//Prepair the where portion of the query if ($pos !== false) {
$this->_query .= ' WHERE '; foreach ($tableData as $prop => $value) {
$i = 1; // determines what data type the item is, for binding purposes.
foreach ($this->_where as $column => $value) { $this->_paramTypeList .= $this->_determineType($value);
// Determines what data type the where column is, for binding purposes.
$this->_whereTypeList .= $this->_determineType($value); // prepares the reset of the SQL query.
$this->_query .= ($prop . ' = ?, ');
// Prepares the reset of the SQL query. }
($i === count($this->_where)) ? $this->_query = rtrim($this->_query, ', ');
$this->_query .= $column . ' = ?': }
$this->_query .= $column . ' = ? AND '; }
$i++; //Prepair the where portion of the query
} $this->_query .= ' WHERE ';
foreach ($this->_where as $column => $value) {
} // Determines what data type the where column is, for binding purposes.
$this->_whereTypeList .= $this->_determineType($value);
// Determine if is INSERT query
if ($hasTableData) { // Prepares the reset of the SQL query.
$pos = strpos($this->_query, 'INSERT'); $this->_query .= ($column . ' = ? AND ');
}
if ($pos !== false) { $this->_query = rtrim($this->_query, ' AND ');
//is insert statement }
$keys = array_keys($tableData);
$values = array_values($tableData); // Determine if is INSERT query
$num = count($keys); if ($hasTableData) {
$pos = strpos($this->_query, 'INSERT');
// wrap values in quotes
foreach ($values as $key => $val) { if ($pos !== false) {
$values[$key] = "'{$val}'"; //is insert statement
$this->_paramTypeList .= $this->_determineType($val); $keys = array_keys($tableData);
} $values = array_values($tableData);
$num = count($keys);
$this->_query .= '(' . implode($keys, ', ') . ')';
$this->_query .= ' VALUES('; // wrap values in quotes
while ($num !== 0) { foreach ($values as $key => $val) {
($num !== 1) ? $this->_query .= '?, ' : $this->_query .= '?)'; $values[$key] = "'{$val}'";
$num--; $this->_paramTypeList .= $this->_determineType($val);
} }
}
} $this->_query .= '(' . implode($keys, ', ') . ')';
$this->_query .= ' VALUES(';
// Did the user set a limit while ($num !== 0) {
if (isset($numRows)) { $this->_query .= '?, ';
$this->_query .= " LIMIT " . (int) $numRows; $num--;
} }
$this->_query = rtrim($this->_query, ', ');
// Prepare query $this->_query .= ')';
$stmt = $this->_prepareQuery(); }
}
// Prepare table data bind parameters
if ($hasTableData) { // Did the user set a limit
$this->_bindParams[0] = $this->_paramTypeList; if (isset($numRows)) {
foreach ($tableData as $prop => $val) { $this->_query .= ' LIMIT ' . (int)$numRows;
array_push($this->_bindParams, $tableData[$prop]); }
}
} // Prepare query
// Prepare where condition bind parameters $stmt = $this->_prepareQuery();
if($hasConditional) {
if ($this->_where) { // Prepare table data bind parameters
$this->_bindParams[0] .= $this->_whereTypeList; if ($hasTableData) {
foreach ($this->_where as $prop => $val) { $this->_bindParams[0] = $this->_paramTypeList;
array_push($this->_bindParams, $this->_where[$prop]); foreach ($tableData as $prop => $val) {
} array_push($this->_bindParams, $tableData[$prop]);
} }
} }
// Bind parameters to statment // Prepare where condition bind parameters
if ($hasTableData || $hasConditional){ if ($hasConditional) {
call_user_func_array(array($stmt, "bind_param"),$this->refValues($this->_bindParams)); if ($this->_where) {
} $this->_bindParams[0] .= $this->_whereTypeList;
foreach ($this->_where as $prop => $val) {
return $stmt; array_push($this->_bindParams, $this->_where[$prop]);
} }
}
/** }
* This helper method takes care of prepared statements' "bind_result method // Bind parameters to statment
* , when the number of variables to pass is unknown. if ($hasTableData || $hasConditional) {
* call_user_func_array(array($stmt, 'bind_param'), $this->refValues($this->_bindParams));
* @param object $stmt Equal to the prepared statement object. }
* @return array The results of the SQL fetch.
*/ return $stmt;
protected function _dynamicBindResults($stmt) }
{
$parameters = array(); /**
$results = array(); * This helper method takes care of prepared statements' "bind_result method
* , when the number of variables to pass is unknown.
$meta = $stmt->result_metadata(); *
* @param mysqli_stmt $stmt Equal to the prepared statement object.
$row = array(); *
while ($field = $meta->fetch_field()) { * @return array The results of the SQL fetch.
$row[$field->name] = NULL; */
$parameters[] = &$row[$field->name]; protected function _dynamicBindResults(mysqli_stmt $stmt)
} {
$parameters = array();
call_user_func_array(array($stmt, "bind_result"),$parameters); $results = array();
while ($stmt->fetch()) { $meta = $stmt->result_metadata();
$x = array();
foreach ($row as $key => $val) { $row = array();
$x[$key] = $val; while ($field = $meta->fetch_field()) {
} $row[$field->name] = null;
array_push($results, $x); $parameters[] = & $row[$field->name];
} }
return $results;
} call_user_func_array(array($stmt, 'bind_result'), $parameters);
/** while ($stmt->fetch()) {
* Method attempts to prepare the SQL query $x = array();
* and throws an error if there was a problem. foreach ($row as $key => $val) {
*/ $x[$key] = $val;
protected function _prepareQuery() }
{ array_push($results, $x);
if (!$stmt = $this->_mysqli->prepare($this->_query)) { }
trigger_error("Problem preparing query ($this->_query) ".$this->_mysqli->error, E_USER_ERROR); return $results;
} }
return $stmt;
} /**
* Method attempts to prepare the SQL query
public function __destruct() * and throws an error if there was a problem.
{ *
$this->_mysqli->close(); * @return mysqli_stmt
} */
protected function _prepareQuery()
function refValues($arr) {
{ if (!$stmt = $this->_mysqli->prepare($this->_query)) {
//Reference is required for PHP 5.3+ trigger_error("Problem preparing query ($this->_query) " . $this->_mysqli->error, E_USER_ERROR);
if (strnatcmp(phpversion(),'5.3') >= 0) { }
$refs = array(); return $stmt;
foreach($arr as $key => $value) }
$refs[$key] = &$arr[$key];
return $refs; /**
} * Close connection
return $arr; */
} public function __destruct()
{
} // END class $this->_mysqli->close();
\ No newline at end of file }
/**
* @param array $arr
*
* @return array
*/
protected function refValues($arr)
{
//Reference is required for PHP 5.3+
if (strnatcmp(phpversion(), '5.3') >= 0) {
$refs = array();
foreach ($arr as $key => $value) {
$refs[$key] = & $arr[$key];
}
return $refs;
}
return $arr;
}
} // END class
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment