Browse Source

Мои изменения в распространяемую библиотеку

master 1.0.2
Misterzym 7 years ago
parent
commit
62351242d8
  1. 246
      safemysql.class.php

246
safemysql.class.php

@ -1,4 +1,5 @@
<?php <?php
/** /**
* @author col.shrapnel@gmail.com * @author col.shrapnel@gmail.com
* @link http://phpfaq.ru/safemysql * @link http://phpfaq.ru/safemysql
@ -65,15 +66,63 @@
* $data = $db->getAll("SELECT * FROM table WHERE ?p", $bar, $sqlpart); * $data = $db->getAll("SELECT * FROM table WHERE ?p", $bar, $sqlpart);
* *
*/ */
class SafeMySQL {
#########################ТВИКИ ОТ ЗУМА######################
/**
* удаляет строки из таблицы, принимает массив вида
* 0=>имя таблицы
* 1=>поле в таблице
* 2=>чему равно
*
* @param array $array
*/
public function removeRows($array) {
foreach ($array as $task) {
$this->query("DELETE FROM ?n WHERE ?n = ?i", $task[0], $task[1], $task[2]);
//$wpdb->delete($task[0], array($task[1] => $task[2]));
}
}
class SafeMySQL /**
{ * Возвращает sql для объединения таблиц
* Принимает массива вида
* array(array('name'=>'table1','field'=>'field1'),array('name'=>'table2','field'=>'field2'));
*
* @param string $sql
*/
public function selectLeftJoin($tables) {
$sql = "SELECT * FROM `" . $tables . "`";
foreach ($ons as $k => $table) {
$sql .= " LEFT JOIN `" . $table[0]['name'] . "` ON `" . $table[1]['name'] . "`.`" . $table[1]['field'] . "`=`" . $table[0]['name'] . "`.`" . $table[0]['field'] . "`";
}
return $sql;
}
/**
* Возвращает стандартную функцию обновления
*
* @return string UPDATE ?n SET ?u WHERE `id` = ?i
*/
public function updTempl() {
return "UPDATE ?n SET ?u WHERE `id` = ?i";
}
/**
* Возвращает стандартную функцию вставки
*
* @return string INSERT INTO ?n SET ?u
*/
public function insTempl() {
return "INSERT INTO ?n SET ?u";
}
############################################################
protected $conn; protected $conn;
protected $stats; protected $stats;
protected $emode; protected $emode;
protected $exname; protected $exname;
protected $defaults = array( protected $defaults = array(
'host' => 'localhost', 'host' => 'localhost',
'user' => 'root', 'user' => 'root',
@ -90,34 +139,28 @@ class SafeMySQL
const RESULT_ASSOC = MYSQLI_ASSOC; const RESULT_ASSOC = MYSQLI_ASSOC;
const RESULT_NUM = MYSQLI_NUM; const RESULT_NUM = MYSQLI_NUM;
function __construct($opt = array()) function __construct($opt = array()) {
{
$opt = array_merge($this->defaults, $opt); $opt = array_merge($this->defaults, $opt);
$this->emode = $opt['errmode']; $this->emode = $opt['errmode'];
$this->exname = $opt['exception']; $this->exname = $opt['exception'];
if (isset($opt['mysqli'])) if (isset($opt['mysqli'])) {
{ if ($opt['mysqli'] instanceof mysqli) {
if ($opt['mysqli'] instanceof mysqli)
{
$this->conn = $opt['mysqli']; $this->conn = $opt['mysqli'];
return; return;
} else { } else {
$this->error("mysqli option must be valid instance of mysqli class"); $this->error("mysqli option must be valid instance of mysqli class");
} }
} }
if ($opt['pconnect']) if ($opt['pconnect']) {
{
$opt['host'] = "p:" . $opt['host']; $opt['host'] = "p:" . $opt['host'];
} }
@$this->conn = mysqli_connect($opt['host'], $opt['user'], $opt['pass'], $opt['db'], $opt['port'], $opt['socket']); @$this->conn = mysqli_connect($opt['host'], $opt['user'], $opt['pass'], $opt['db'], $opt['port'], $opt['socket']);
if ( !$this->conn ) if (!$this->conn) {
{
$this->error(mysqli_connect_errno() . " " . mysqli_connect_error()); $this->error(mysqli_connect_errno() . " " . mysqli_connect_error());
} }
@ -135,8 +178,7 @@ class SafeMySQL
* @param mixed $arg,... unlimited number of arguments to match placeholders in the query * @param mixed $arg,... unlimited number of arguments to match placeholders in the query
* @return resource|FALSE whatever mysqli_query returns * @return resource|FALSE whatever mysqli_query returns
*/ */
public function query() public function query() {
{
return $this->rawQuery($this->prepareQuery(func_get_args())); return $this->rawQuery($this->prepareQuery(func_get_args()));
} }
@ -147,8 +189,7 @@ class SafeMySQL
* @param int $mode - optional fetch mode, RESULT_ASSOC|RESULT_NUM, default RESULT_ASSOC * @param int $mode - optional fetch mode, RESULT_ASSOC|RESULT_NUM, default RESULT_ASSOC
* @return array|FALSE whatever mysqli_fetch_array returns * @return array|FALSE whatever mysqli_fetch_array returns
*/ */
public function fetch($result,$mode=self::RESULT_ASSOC) public function fetch($result, $mode = self::RESULT_ASSOC) {
{
return mysqli_fetch_array($result, $mode); return mysqli_fetch_array($result, $mode);
} }
@ -157,8 +198,7 @@ class SafeMySQL
* *
* @return int whatever mysqli_affected_rows returns * @return int whatever mysqli_affected_rows returns
*/ */
public function affectedRows() public function affectedRows() {
{
return mysqli_affected_rows($this->conn); return mysqli_affected_rows($this->conn);
} }
@ -167,8 +207,7 @@ class SafeMySQL
* *
* @return int whatever mysqli_insert_id returns * @return int whatever mysqli_insert_id returns
*/ */
public function insertId() public function insertId() {
{
return mysqli_insert_id($this->conn); return mysqli_insert_id($this->conn);
} }
@ -178,16 +217,14 @@ class SafeMySQL
* @param resource $result - myqli result * @param resource $result - myqli result
* @return int whatever mysqli_num_rows returns * @return int whatever mysqli_num_rows returns
*/ */
public function numRows($result) public function numRows($result) {
{
return mysqli_num_rows($result); return mysqli_num_rows($result);
} }
/** /**
* Conventional function to free the resultset. * Conventional function to free the resultset.
*/ */
public function free($result) public function free($result) {
{
mysqli_free_result($result); mysqli_free_result($result);
} }
@ -202,11 +239,9 @@ class SafeMySQL
* @param mixed $arg,... unlimited number of arguments to match placeholders in the query * @param mixed $arg,... unlimited number of arguments to match placeholders in the query
* @return string|FALSE either first column of the first row of resultset or FALSE if none found * @return string|FALSE either first column of the first row of resultset or FALSE if none found
*/ */
public function getOne() public function getOne() {
{
$query = $this->prepareQuery(func_get_args()); $query = $this->prepareQuery(func_get_args());
if ($res = $this->rawQuery($query)) if ($res = $this->rawQuery($query)) {
{
$row = $this->fetch($res); $row = $this->fetch($res);
if (is_array($row)) { if (is_array($row)) {
return reset($row); return reset($row);
@ -227,8 +262,7 @@ class SafeMySQL
* @param mixed $arg,... unlimited number of arguments to match placeholders in the query * @param mixed $arg,... unlimited number of arguments to match placeholders in the query
* @return array|FALSE either associative array contains first row of resultset or FALSE if none found * @return array|FALSE either associative array contains first row of resultset or FALSE if none found
*/ */
public function getRow() public function getRow() {
{
$query = $this->prepareQuery(func_get_args()); $query = $this->prepareQuery(func_get_args());
if ($res = $this->rawQuery($query)) { if ($res = $this->rawQuery($query)) {
$ret = $this->fetch($res); $ret = $this->fetch($res);
@ -249,14 +283,11 @@ class SafeMySQL
* @param mixed $arg,... unlimited number of arguments to match placeholders in the query * @param mixed $arg,... unlimited number of arguments to match placeholders in the query
* @return array|FALSE either enumerated array of first fields of all rows of resultset or FALSE if none found * @return array|FALSE either enumerated array of first fields of all rows of resultset or FALSE if none found
*/ */
public function getCol() public function getCol() {
{
$ret = array(); $ret = array();
$query = $this->prepareQuery(func_get_args()); $query = $this->prepareQuery(func_get_args());
if ( $res = $this->rawQuery($query) ) if ($res = $this->rawQuery($query)) {
{ while ($row = $this->fetch($res)) {
while($row = $this->fetch($res))
{
$ret[] = reset($row); $ret[] = reset($row);
} }
$this->free($res); $this->free($res);
@ -275,14 +306,11 @@ class SafeMySQL
* @param mixed $arg,... unlimited number of arguments to match placeholders in the query * @param mixed $arg,... unlimited number of arguments to match placeholders in the query
* @return array enumerated 2d array contains the resultset. Empty if no rows found. * @return array enumerated 2d array contains the resultset. Empty if no rows found.
*/ */
public function getAll() public function getAll() {
{
$ret = array(); $ret = array();
$query = $this->prepareQuery(func_get_args()); $query = $this->prepareQuery(func_get_args());
if ( $res = $this->rawQuery($query) ) if ($res = $this->rawQuery($query)) {
{ while ($row = $this->fetch($res)) {
while($row = $this->fetch($res))
{
$ret[] = $row; $ret[] = $row;
} }
$this->free($res); $this->free($res);
@ -302,17 +330,14 @@ class SafeMySQL
* @param mixed $arg,... unlimited number of arguments to match placeholders in the query * @param mixed $arg,... unlimited number of arguments to match placeholders in the query
* @return array - associative 2d array contains the resultset. Empty if no rows found. * @return array - associative 2d array contains the resultset. Empty if no rows found.
*/ */
public function getInd() public function getInd() {
{
$args = func_get_args(); $args = func_get_args();
$index = array_shift($args); $index = array_shift($args);
$query = $this->prepareQuery($args); $query = $this->prepareQuery($args);
$ret = array(); $ret = array();
if ( $res = $this->rawQuery($query) ) if ($res = $this->rawQuery($query)) {
{ while ($row = $this->fetch($res)) {
while($row = $this->fetch($res))
{
$ret[$row[$index]] = $row; $ret[$row[$index]] = $row;
} }
$this->free($res); $this->free($res);
@ -331,17 +356,14 @@ class SafeMySQL
* @param mixed $arg,... unlimited number of arguments to match placeholders in the query * @param mixed $arg,... unlimited number of arguments to match placeholders in the query
* @return array - associative array contains key=value pairs out of resultset. Empty if no rows found. * @return array - associative array contains key=value pairs out of resultset. Empty if no rows found.
*/ */
public function getIndCol() public function getIndCol() {
{
$args = func_get_args(); $args = func_get_args();
$index = array_shift($args); $index = array_shift($args);
$query = $this->prepareQuery($args); $query = $this->prepareQuery($args);
$ret = array(); $ret = array();
if ( $res = $this->rawQuery($query) ) if ($res = $this->rawQuery($query)) {
{ while ($row = $this->fetch($res)) {
while($row = $this->fetch($res))
{
$key = $row[$index]; $key = $row[$index];
unset($row[$index]); unset($row[$index]);
$ret[$key] = reset($row); $ret[$key] = reset($row);
@ -373,8 +395,7 @@ class SafeMySQL
* @param mixed $arg,... unlimited number of arguments to match placeholders in the expression * @param mixed $arg,... unlimited number of arguments to match placeholders in the expression
* @return string - initial expression with placeholders substituted with data. * @return string - initial expression with placeholders substituted with data.
*/ */
public function parse() public function parse() {
{
return $this->prepareQuery(func_get_args()); return $this->prepareQuery(func_get_args());
} }
@ -398,8 +419,7 @@ class SafeMySQL
* @param string $default - optional variable to set if no match found. Default to false. * @param string $default - optional variable to set if no match found. Default to false.
* @return string|FALSE - either sanitized value or FALSE * @return string|FALSE - either sanitized value or FALSE
*/ */
public function whiteList($input,$allowed,$default=FALSE) public function whiteList($input, $allowed, $default = FALSE) {
{
$found = array_search($input, $allowed); $found = array_search($input, $allowed);
return ($found === FALSE) ? $default : $allowed[$found]; return ($found === FALSE) ? $default : $allowed[$found];
} }
@ -420,12 +440,9 @@ class SafeMySQL
* @param array $allowed - an array with allowed field names * @param array $allowed - an array with allowed field names
* @return array filtered out source array * @return array filtered out source array
*/ */
public function filterArray($input,$allowed) public function filterArray($input, $allowed) {
{ foreach (array_keys($input) as $key) {
foreach(array_keys($input) as $key ) if (!in_array($key, $allowed)) {
{
if ( !in_array($key,$allowed) )
{
unset($input[$key]); unset($input[$key]);
} }
} }
@ -437,8 +454,7 @@ class SafeMySQL
* *
* @return string|NULL either last executed query or NULL if were none * @return string|NULL either last executed query or NULL if were none
*/ */
public function lastQuery() public function lastQuery() {
{
$last = end($this->stats); $last = end($this->stats);
return $last['query']; return $last['query'];
} }
@ -448,8 +464,7 @@ class SafeMySQL
* *
* @return array contains all executed queries with timings and errors * @return array contains all executed queries with timings and errors
*/ */
public function getStats() public function getStats() {
{
return $this->stats; return $this->stats;
} }
@ -460,8 +475,7 @@ class SafeMySQL
* @param string $query - a regular SQL query * @param string $query - a regular SQL query
* @return mysqli result resource or FALSE on error * @return mysqli result resource or FALSE on error
*/ */
protected function rawQuery($query) protected function rawQuery($query) {
{
$start = microtime(TRUE); $start = microtime(TRUE);
$res = mysqli_query($this->conn, $query); $res = mysqli_query($this->conn, $query);
$timer = microtime(TRUE) - $start; $timer = microtime(TRUE) - $start;
@ -471,8 +485,7 @@ class SafeMySQL
'start' => $start, 'start' => $start,
'timer' => $timer, 'timer' => $timer,
); );
if (!$res) if (!$res) {
{
$error = mysqli_error($this->conn); $error = mysqli_error($this->conn);
end($this->stats); end($this->stats);
@ -486,29 +499,24 @@ class SafeMySQL
return $res; return $res;
} }
protected function prepareQuery($args) protected function prepareQuery($args) {
{
$query = ''; $query = '';
$raw = array_shift($args); $raw = array_shift($args);
$array = preg_split('~(\?[nsiuap])~u', $raw, null, PREG_SPLIT_DELIM_CAPTURE); $array = preg_split('~(\?[nsiuap])~u', $raw, null, PREG_SPLIT_DELIM_CAPTURE);
$anum = count($args); $anum = count($args);
$pnum = floor(count($array) / 2); $pnum = floor(count($array) / 2);
if ( $pnum != $anum ) if ($pnum != $anum) {
{
$this->error("Number of args ($anum) doesn't match number of placeholders ($pnum) in [$raw]"); $this->error("Number of args ($anum) doesn't match number of placeholders ($pnum) in [$raw]");
} }
foreach ($array as $i => $part) foreach ($array as $i => $part) {
{ if (($i % 2) == 0) {
if ( ($i % 2) == 0 )
{
$query .= $part; $query .= $part;
continue; continue;
} }
$value = array_shift($args); $value = array_shift($args);
switch ($part) switch ($part) {
{
case '?n': case '?n':
$part = $this->escapeIdent($value); $part = $this->escapeIdent($value);
break; break;
@ -533,90 +541,72 @@ class SafeMySQL
return $query; return $query;
} }
protected function escapeInt($value) protected function escapeInt($value) {
{ if ($value === NULL) {
if ($value === NULL)
{
return 'NULL'; return 'NULL';
} }
if(!is_numeric($value)) if (!is_numeric($value)) {
{
$this->error("Integer (?i) placeholder expects numeric value, " . gettype($value) . " given"); $this->error("Integer (?i) placeholder expects numeric value, " . gettype($value) . " given");
return FALSE; return FALSE;
} }
if (is_float($value)) if (is_float($value)) {
{
$value = number_format($value, 0, '.', ''); // may lose precision on big numbers $value = number_format($value, 0, '.', ''); // may lose precision on big numbers
} }
return $value; return $value;
} }
protected function escapeString($value) protected function escapeString($value) {
{ if ($value === NULL) {
if ($value === NULL)
{
return 'NULL'; return 'NULL';
} }
return "'" . mysqli_real_escape_string($this->conn, $value) . "'"; return "'" . mysqli_real_escape_string($this->conn, $value) . "'";
} }
protected function escapeIdent($value) protected function escapeIdent($value) {
{ if ($value) {
if ($value)
{
return "`" . str_replace("`", "``", $value) . "`"; return "`" . str_replace("`", "``", $value) . "`";
} else { } else {
$this->error("Empty value for identifier (?n) placeholder"); $this->error("Empty value for identifier (?n) placeholder");
} }
} }
protected function createIN($data) protected function createIN($data) {
{ if (!is_array($data)) {
if (!is_array($data))
{
$this->error("Value for IN (?a) placeholder should be array"); $this->error("Value for IN (?a) placeholder should be array");
return; return;
} }
if (!$data) if (!$data) {
{
return 'NULL'; return 'NULL';
} }
$query = $comma = ''; $query = $comma = '';
foreach ($data as $value) foreach ($data as $value) {
{
$query .= $comma . $this->escapeString($value); $query .= $comma . $this->escapeString($value);
$comma = ","; $comma = ",";
} }
return $query; return $query;
} }
protected function createSET($data) protected function createSET($data) {
{ if (!is_array($data)) {
if (!is_array($data))
{
$this->error("SET (?u) placeholder expects array, " . gettype($data) . " given"); $this->error("SET (?u) placeholder expects array, " . gettype($data) . " given");
return; return;
} }
if (!$data) if (!$data) {
{
$this->error("Empty array for SET (?u) placeholder"); $this->error("Empty array for SET (?u) placeholder");
return; return;
} }
$query = $comma = ''; $query = $comma = '';
foreach ($data as $key => $value) foreach ($data as $key => $value) {
{
$query .= $comma . $this->escapeIdent($key) . '=' . $this->escapeString($value); $query .= $comma . $this->escapeIdent($key) . '=' . $this->escapeString($value);
$comma = ","; $comma = ",";
} }
return $query; return $query;
} }
protected function error($err) protected function error($err) {
{
$err = __CLASS__ . ": " . $err; $err = __CLASS__ . ": " . $err;
if ( $this->emode == 'error' ) if ($this->emode == 'error') {
{
$err .= ". Error initiated in " . $this->caller() . ", thrown"; $err .= ". Error initiated in " . $this->caller() . ", thrown";
trigger_error($err, E_USER_ERROR); trigger_error($err, E_USER_ERROR);
} else { } else {
@ -624,14 +614,11 @@ class SafeMySQL
} }
} }
protected function caller() protected function caller() {
{
$trace = debug_backtrace(); $trace = debug_backtrace();
$caller = ''; $caller = '';
foreach ($trace as $t) foreach ($trace as $t) {
{ if (isset($t['class']) && $t['class'] == __CLASS__) {
if ( isset($t['class']) && $t['class'] == __CLASS__ )
{
$caller = $t['file'] . " on line " . $t['line']; $caller = $t['file'] . " on line " . $t['line'];
} else { } else {
break; break;
@ -644,13 +631,12 @@ class SafeMySQL
* On a long run we can eat up too much memory with mere statsistics * On a long run we can eat up too much memory with mere statsistics
* Let's keep it at reasonable size, leaving only last 100 entries. * Let's keep it at reasonable size, leaving only last 100 entries.
*/ */
protected function cutStats() protected function cutStats() {
{ if (count($this->stats) > 100) {
if ( count($this->stats) > 100 )
{
reset($this->stats); reset($this->stats);
$first = key($this->stats); $first = key($this->stats);
unset($this->stats[$first]); unset($this->stats[$first]);
} }
} }
} }

Loading…
Cancel
Save