MYSQLi Class
Please understand that using something like this in a modern application is a bad idea. This was created before PDO and Query Builders like those seen in Laravel, CodeIgniter, etc. I highly recommend Laravel if you are looking for a better way.
PHP class to access MySQL database wrapper using MySQLi
This class can:
- Connect to a given MySQL server
- Execute SQL queries
- Retrieve the number of query result rows, result columns and last inserted id
- Retrieve the query results in a single array
- Escape a single string or an array of literal text values to use in queries
- Determine if one value or an array of values contain common MySQL function calls
- Check of a table exists
- Check of a given table record exists
- Return a query result that has just one row
- Execute INSERT, UPDATE, UPSERT(!!!) and DELETE queries from values that define tables, field names, field values and conditions
- Truncate a table or tables
- Optimize a table or tables
- Send email messages with MySQL access and query errors
- Display the total number of queries performed during all instances of the class
Usage
require_once "class.db.php";
$db = new DB();
foreach( $db->getResults( "SELECT * FROM users_table" ) as $result )
{
$name = $result['name'];
$email = $result['email'];
echo "Name: $name" . "<br />" . "Email: $email" . "<br /><br />";
}
Stored Procedures
showProcedure($procedure)
callProcedure($procedure, $params = array(), $responses = array())
Filtering
filter($data)
escape($data)
clean($data)
Queries (Getting Data)
query($query)
getArray($query, $type = MYSQLI_ASSOC)
getRow($query, $object = false)
getResult($query, $pos = 0)
getResults($query, $object = false)
Queries (Storing Data)
insert($table, $variables = array())
insertMulti($table, $columns = array(), $records = array())
update($table, $variables = array(), $where = array(), $limit = null)
upsert($table, $data = array(), $where = array())
Checks
tableExists($table)
numRows($query)
exists($table = '', $check_val = '', $params = array())
Utilities
search($table, $where = array(), $limit = null)
delete($table, $where = array(), $limit = null)
affected()
numFields($query)
showColumns($table)
truncate($tables = array())
optimize($tables = array())
totalQueries()
lastQuery()
lastId()
<?php
/** * PHP MYSQLi Database Class * * This class helps developers make standardized calls across their entire * application. This class was found and forked (bennettstone/simple-mysqli) * as a necessity after mysql_connect was deprecated and my site crashed. I * was forced to go through each and every page of my site and edit each call * and thought there had to be a better way. Please feel free to use on your * site and submit issues where necessary. Thank you and happy coding. * * * @link https://github.com/nowendwell/mysqli-class * @version 2.0.1 * * Description: A MYSQLi database wrapper for PHP * Last Update: 2018-04-05 * Author: Ben Miller * License: MIT * License URI: https://opensource.org/licenses/MIT */ class DB { // DB Connection Settings private $db_name = 'YOUR_DB_NAME'; private $db_user = 'YOUR_DB_USER'; private $db_pass = 'YOUR_DB_PASS'; private $db_host = 'YOUR_DB_HOST'; private $db_charset = 'utf8'; // Debug Settings public $debug = true; public $display_errors = true; public $send_mail = true; public $send_to = null; public $transactions = false; public $log_path = 'queries.log'; // Class Settings private $link = null; public $filter; public static $inst = null; public static $counter = 0; public $queries = array(); public function __construct() { $args = func_get_args(); if (sizeof($args) > 0) { $this->link = new mysqli($args[0], $args[1], $args[2], $args[3]); } else { $this->link = new mysqli($this->db_host, $this->db_user, $this->db_pass, $this->db_name); } if ($this->link->connect_errno) { $this->logDbErrors("Connect failed", $this->link->connect_error); exit("connect failed"); } $this->link->set_charset($this->db_charset); } public function __destruct() { if ($this->link) { $this->disconnect(); } } private function logQueries($query) { $this->queries[] = $query; if ($this->debug === true) { $string = "[" . date("Y-m-d h:i:s A T") . "]" . "\t$query\n"; // appends to file, creates if doesn't exist file_put_contents($this->log_path, $string, FILE_APPEND | LOCK_EX); } } /** * Show the definition of a Procedure * * @access public * @param string (Name of the procedure) * @param bool $object (true returns object) * @return array */ public function showProcedure($procedure, $object = false) { if (empty($procedure)) { return false; } //Overwrite the $row var to null $row = null; $results = $this->link->query("SHOW CREATE PROCEDURE {$procedure}"); if ($this->link->error) { $this->logDbErrors($this->link->error, $procedure); return false; } else { $row = array(); while ($r = (!$object) ? $results->fetch_assoc() : $results->fetch_object()) { $row[] = $r; } return $row; } } /** * Call Procedure with parameters * * @param string $procedure Name of procedure * @param array $params "param"=>"value" * @param array $responses * @return bool */ public function callProcedure($procedure, $params = array(), $responses = array()) { $sql = "CALL {$procedure}( "; $param_sql = array(); foreach ($params as $field => $value) { if ($value === null) { $param_sql[] = "@{$field} := NULL"; } else { if (is_numeric($value)) { $param_sql[] = "@{$field} := {$value}"; } else { $param_sql[] = "@{$field} := '{$value}'"; } } } foreach ($responses as $field) { $param_sql[] = "@{$field}"; } $sql .= implode(', ', $param_sql); $sql .= ' )'; $query = $this->query($sql); return $query; } /** * Show the definition of a Function * * @access public * @param string (Name of the function) * @param bool $object (true returns object) * @return array */ public function showFunction($function, $object = false) { if (empty($function)) { return false; } $results = $this->query("SHOW CREATE FUNCTION {$function}"); $row = array(); while ($r = (!$object) ? $results->fetch_assoc() : $results->fetch_object()) { $row[] = $r; } return $row; } /** * Allow the class to send admins a message alerting them to errors * on production sites * * @access public * @param string $error * @param string $query * @return mixed */ public function logDbErrors($error, $query) { if ($this->debug == true) { if ($this->send_to != null) { $message = "<p>Error at ". date("Y-m-d H:i:s").":</p>"; $message .= "<p>Query: ". htmlentities($query)."<br />"; $message .= "Error: {$error}<br />"; $message .= "Page: " . $_SERVER["REQUEST_URI"] ."<br />"; $message .= "</p>"; $headers = "MIME-Version: 1.0" . "\r\n"; $headers .= "Content-type: text/html; charset=iso-8859-1" . "\r\n"; $headers .= "To: Admin <{$this->send_to}>\r\n"; $headers .= "From: Admin <{$this->send_to}>\r\n"; mail($this->send_to, 'Database Error', $message, $headers); } if ($this->display_errors) { echo $error; } } } /** * Sanitize user data * * Example usage: * $user_name = $db->filter( $_POST['user_name'] ); * * Or to filter an entire array: * $data = array( 'name' => $_POST['name'], 'email' => 'email@address.com' ); * $data = $db->filter( $data ); * * @access public * @param mixed $data * @return mixed $data */ public function filter($data) { if (!is_array($data)) { $data = $this->link->real_escape_string($data); $data = trim(htmlentities($data, ENT_QUOTES, 'UTF-8', false)); } else { //Self call function to sanitize array data $data = array_map(array( $this, 'filter' ), $data); } return $data; } /** * Extra function to filter when only mysqli_real_escape_string is needed * @access public * @param mixed $data * @return mixed $data */ public function escape($data) { if (!is_array($data)) { $data = $this->link->real_escape_string($data); } else { //Self call function to sanitize array data $data = array_map(array( $this, 'escape' ), $data); } return $data; } /** * Normalize sanitized data for display (reverse $db->filter cleaning) * * Example usage: * echo $db->clean( $data_from_database ); * * @access public * @param string $data * @return string $data */ public function clean($data) { $data = stripslashes($data); $data = html_entity_decode($data, ENT_QUOTES, $this->db_charset); $data = nl2br($data); $data = urldecode($data); return $data; } /** * Determine if common non-encapsulated fields are being used * * Example usage: * if( $db->dbCommon( $query ) ) * { * //Do something * } * Used by function exists * * @access public * @param string * @param array * @return bool * */ public function dbCommon($value = '') { if (is_array($value)) { foreach ($value as $v) { if (preg_match('/AES_DECRYPT/i', $v) || preg_match('/AES_ENCRYPT/i', $v) || preg_match('/now()/i', $v) || preg_match('/NOW()/i', $v)) { return true; } else { return false; } } } else { if (preg_match('/AES_DECRYPT/i', $value) || preg_match('/AES_ENCRYPT/i', $value) || preg_match('/now()/i', $value) || preg_match('/NOW()/i', $value)) { return true; } } } /** * Perform queries * All following functions run through this function * * @access public * @param string * @return string * @return array * @return bool * */ public function query($query) { self::$counter++; $this->logQueries($query); if ($this->transactions == true) { $this->link->query('START TRANSACTION;'); } $full_query = $this->link->query($query); if ($this->transactions == true) { $this->link->query('COMMIT;'); } if ($this->link->error) { $this->logDbErrors($this->link->error, $query); if ($this->transactions == true) { $this->link->query('ROLLBACK;'); } return false; } else { return $full_query; } } /** * Determine if database table exists * Example usage: * if( !$db->tableExists( 'checkingfortable' ) ) * { * //Install your table or throw error * } * * @access public * @param string * @return bool * */ public function tableExists($table) { $check = $this->query("SELECT * FROM information_schema.tables WHERE table_schema = '{$this->db_name}' AND table_name = '{$table}' LIMIT 1;"); if ($check !== false) { if ($check->num_rows > 0) { return true; } else { return false; } } else { return false; } } /** * Count number of rows found matching a specific query * * Example usage: * $rows = $db->numRows( "SELECT id FROM users WHERE user_id = 44" ); * * @access public * @param string * @return int * */ public function numRows($query) { $query = $this->query($query); return $query->num_rows; } /** * Run check to see if value exists, returns true or false * * Example Usage: * $check_user = array( * 'user_email' => 'someuser@gmail.com', * 'user_id' => 48 * ); * $exists = $db->exists( 'your_table', 'user_id', $check_user ); * * @access public * @param string database table name * @param string field to check (i.e. 'user_id' or COUNT(user_id)) * @param array column name => column value to match * @return bool * */ public function exists($table = '', $check_val = '', $params = array()) { if (empty($table) || empty($check_val) || empty($params)) { return false; } $check = array(); foreach ($params as $field => $value) { if (!empty($field) && !empty($value)) { //Check for frequently used mysql commands and prevent encapsulation of them if ($this->dbCommon($value)) { $check[] = "`{$field}` = {$value}"; } else { $check[] = "`{$field}` = '{$value}'"; } } } $check = implode(' AND ', $check); $rs_check = "SELECT {$check_val} FROM `{$table}` WHERE {$check}"; $number = $this->numRows($rs_check); if ($number === 0) { return false; } else { return true; } } /** * Return specific row based on db query * * Example usage: * list( $name, $email ) = $db->get_array( "SELECT name, email FROM users WHERE user_id = 44" ); * * @access public * @param string * @param bool $object (true returns results as objects) * @return array * */ public function getArray($query, $type = MYSQLI_ASSOC) { $row = $this->query($query); while ($q = $row->fetch_array($type)) { $r[] = $q; } return $r; } /** * Return specific row based on db query * * Example usage: * list( $name, $email ) = $db->getRow( "SELECT name, email FROM users WHERE user_id = 44" ); * * @access public * @param string * @param bool $object (true returns results as objects) * @return array * */ public function getRow($query, $object = false) { $row = $this->query($query); $r = (!$object) ? $row->fetch_assoc() : $row->fetch_object(); return $r; } /** * Perform query to retrieve single result * * Example usage: * echo $db->getResult( "SELECT name, email FROM users ORDER BY name ASC" ); * * @access public * @param string * @param int|string (Can be either position in the array or the name of the returned field) * @return string * */ public function getResult($query, $pos = 0) { $results = $this->query($query); $result = $results->fetch_array(); return $result[$pos]; } /** * Perform query to retrieve array of associated results * * Example usage: * $users = $db->getResults( "SELECT name, email FROM users ORDER BY name ASC" ); * foreach( $users as $user ) * { * echo $user['name'] . ': '. $user['email'] .'<br />'; * } * * @access public * @param string * @param bool $object (true returns object) * @return array * */ public function getResults($query, $object = false) { $results = $this->query($query); $row = array(); while ($r = (!$object) ? $results->fetch_assoc() : $results->fetch_object()) { $row[] = $r; } return $row; } /** * Insert data into database table * * Example usage: * $user_data = array( * 'name' => 'Bennett', * 'email' => 'email@address.com', * 'active' => 1 * ); * $db->insert( 'users_table', $user_data ); * * @access public * @param string table name * @param array table column => column value * @return bool * */ public function insert($table, $variables = array()) { //Make sure the array isn't empty if (empty($variables)) { return false; } $variables = $this->filter($variables); $sql = "INSERT INTO {$table}"; $fields = array(); $values = array(); foreach ($variables as $field => $value) { $fields[] = $field; if ($value === null) { $values[] = "NULL"; } else { $values[] = "'{$value}'"; } } $fields = " (`" . implode("`, `", $fields) . "`)"; $values = "(". implode(", ", $values) .")"; $sql .= $fields ." VALUES {$values};"; $query = $this->query($sql); return $query; } /** * Insert multiple records in a single query into a database table * * Example usage: * $fields = array( * 'name', * 'email', * 'active' * ); * $records = array( * array( * 'Bennett', 'bennett@email.com', 1 * ), * array( * 'Lori', 'lori@email.com', 0 * ), * array( * 'Nick', 'nick@nick.com', 1, 'This will not be added' * ), * array( * 'Meghan', 'meghan@email.com', 1 * ) * ); * $db->insertMulti( 'users_table', $fields, $records ); * * @access public * @param string table name * @param array table columns * @param array records * @return bool * @return int number of records inserted * */ public function insertMulti($table, $columns = array(), $records = array()) { //Make sure the arrays aren't empty if (empty($columns) || empty($records)) { return false; } //Count the number of fields to ensure insertion statements do not exceed the same num $number_columns = count($columns); //Start a counter for the rows $added = 0; //Start the query $sql = "INSERT INTO {$table}"; $fields = array(); //Loop through the columns for insertion preparation foreach ($columns as $field) { $fields[] = "`{$field}`"; } $fields = ' (`' . implode('`, `', $fields) . '`)'; //Loop through the records to insert $values = array(); $records = $this->filter($records); foreach ($records as $record) { //Only add a record if the values match the number of columns if (count($record) == $number_columns) { $values[] = "('" . implode("', '", array_values($record)) ."')"; $added++; } } $values = implode(', ', $values); $sql .= $fields . " VALUES {$values}"; $query = $this->query($sql); return $query; } /** * Search data in database table * * Example usage: * $where = array( 'user_id' => 44, 'name' => 'Bennett' ); * $db->search( 'users', $where ); * * @access public * @param string table name * @param array where parameters table column => column value * @param int limit * @return mixed * */ public function search($table, $where = array(), $limit = null) { if (empty($where)) { return false; } $where = $this->filter($where); $sql = "SELECT * FROM `{$table}`"; //Add the $where clauses as needed if (!empty($where)) { foreach ($where as $field => $value) { $clause[] = "`{$field}` = '{$value}'"; } $sql .= ' WHERE '. implode(' AND ', $clause); } if ($limit !== null) { $sql .= " LIMIT {$limit}"; } return $this->getResults($sql); } /** * Update data in database table * * Example usage: * $update = array( 'name' => 'Not bennett', 'email' => 'someotheremail@email.com' ); * $where = array( 'user_id' => 44, 'name' => 'Bennett' ); * $db->update( 'users_table', $update, $where, 1 ); * * @access public * @param string table name * @param array values to update table column => column value * @param array where parameters table column => column value * @param int limit * @return bool * */ public function update($table, $variables = array(), $where = array(), $limit = null) { if (empty($variables)) { return false; } $variables = $this->filter($variables); $sql = "UPDATE {$table} SET "; foreach ($variables as $field => $value) { if ($value === null) { $updates[] = "`{$field}` = NULL"; } else { $updates[] = "`{$field}` = '{$value}'"; } } $sql .= implode(', ', $updates); //Add the $where clauses as needed if (!empty($where)) { foreach ($where as $field => $value) { $value = $value; $clause[] = "`{$field}` = '{$value}'"; } $sql .= ' WHERE '. implode(' AND ', $clause); } if ($limit !== null) { $sql .= " LIMIT {$limit}"; } $query = $this->query($sql); return $query; } /** * Upserts data into database table * * Example usage: * $data = array( * 'name' => 'Jon' * ); * $where = array( * 'name' => 'Bennett', * 'email' => 'email@address.com', * 'active' => 1 * ); * $db->upsert( 'users_table', $data, $where); * * @access public * @param string table name * @param array table column => column value * @return bool * */ public function upsert($table, $data = array(), $where = array()) { //Make sure the args aren't empty if (empty($table) || empty($data) || empty($where)) { return false; } // Find if the row exists $find = $this->search($table, $where); // if the row exists, update, if not, insert if (empty($find)) { return $this->insert($table, $data); } else { return $this->update($table, $data, $where); } } /** * Delete data from table * * Example usage: * $where = array( 'user_id' => 44, 'email' => 'someotheremail@email.com' ); * $db->delete( 'users_table', $where, 1 ); * * @access public * @param string table name * @param array where parameters table column => column value * @param int max number of rows to remove. * @return bool * */ public function delete($table, $where = array(), $limit = null) { //Delete clauses require a where param, otherwise use "truncate" if (empty($where)) { return false; } $sql = "DELETE FROM `{$table}`"; foreach ($where as $field => $value) { $value = $value; $clause[] = "`{$field}` = '{$value}'"; } $sql .= " WHERE ". implode(' AND ', $clause); if ($limit !== null) { $sql .= " LIMIT {$limit}"; } $query = $this->query($sql); return $query; } /** * Get last auto-incrementing ID associated with an insertion * * Example usage: * $db->insert( 'users_table', $user ); * $last = $db->lastid(); * * @access public * @return int * */ public function lastId() { return $this->link->insert_id; } /** * Return the number of rows affected by a given query * * Example usage: * $db->insert( 'users_table', $user ); * $db->affected(); * * @access public * @param none * @return int */ public function affected() { return $this->link->affected_rows; } /** * Get number of fields * * Example usage: * echo $db->numFields( "SELECT * FROM users_table" ); * * @access public * @param query * @return int */ public function numFields($query) { $query = $this->query($query); $fields = $query->field_count; return $fields; } /** * Get columns from associated table * * Example usage: * $fields = $db->showColumns( "users_table" ); * echo '<pre>'; * print_r( $fields ); * echo '</pre>'; * * @access public * @param string * @return array */ public function showColumns($table) { $query = $this->getResults("SHOW COLUMNS FROM `{$table}`;"); return $query; } /** * Truncate entire tables * * Example usage: * $remove_tables = array( 'users_table', 'user_data' ); * echo $db->truncate( $remove_tables ); * * @access public * @param array database table names * @return int number of tables truncated * */ public function truncate($tables = array()) { if (!empty($tables)) { $truncated = 0; foreach ($tables as $table) { $table = trim($table); $truncate = "TRUNCATE TABLE `{$table}`"; $this->query($truncate); $truncated++; } return $truncated; } } /** * Optimize tables * * Example usage: * $tables = array( 'users_table', 'user_data' ); * echo $db->optimize( $tables ); * * @access public * @param array database table names * @return int number of tables truncated * */ public function optimize($tables = array()) { if (!empty($tables)) { $optimized = 0; foreach ($tables as $table) { $table = trim($table); $optimize = "OPTIMIZE TABLE `{$table}`"; $this->query($optimize); $optimized++; } return $optimized; } } /** * Output the total number of queries * Generally designed to be used at the bottom of a page after * scripts have been run and initialized as needed * * Example usage: * echo 'There were '. $db->totalQueries() . ' performed'; * * @access public * @param none * @return int */ public function totalQueries() { return self::$counter; } /** * Get the last query * * Example usage: * echo $db->lastQuery(); * * @access public * @return string */ public function lastQuery() { $last_query = array_values(array_slice($this->queries, -1))[0]; return $last_query; } /** * Singleton function * * Example usage: * $db = DB::getInstance(); * * @access private * @return self */ public static function getInstance() { if (self::$inst == null) { self::$inst = new DB(); } return self::$inst; } /** * Disconnect from db server * Called automatically from __destruct function */ public function disconnect() { $this->link->close(); } } //end class DB
0 Comments