OO mysql
commit
31d27904d2
|
@ -0,0 +1,394 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Very stable interface for MySQL - object-oriented at last :)
|
||||
* Select builder is inspired by MediaWiki's one.
|
||||
* (c) Vitaliy Filippov, 2012
|
||||
*/
|
||||
|
||||
define('MS_HASH', 0);
|
||||
define('MS_LIST', 1);
|
||||
define('MS_ROW', 2);
|
||||
define('MS_ONE', 2);
|
||||
define('MS_COL', 4);
|
||||
define('MS_VALUE', 6);
|
||||
define('MS_RESULT', 8);
|
||||
|
||||
class DatabaseMysql
|
||||
{
|
||||
var $dbName;
|
||||
var $link;
|
||||
var $tableNames = array();
|
||||
var $queryCount = 0;
|
||||
var $queryLogFile;
|
||||
|
||||
function __construct($host, $username, $password, $dbname, $port = NULL, $socket = NULL)
|
||||
{
|
||||
if ($socket !== NULL)
|
||||
{
|
||||
$this->link = new mysqli($host, $username, $password, $dbname, $port, $socket);
|
||||
}
|
||||
elseif ($port !== NULL)
|
||||
{
|
||||
$this->link = new mysqli($host, $username, $password, $dbname, $port);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->link = new mysqli($host, $username, $password, $dbname);
|
||||
}
|
||||
$this->dbName = $dbname;
|
||||
}
|
||||
|
||||
function getDBName()
|
||||
{
|
||||
return $this->dbName;
|
||||
}
|
||||
|
||||
function quoteId($name)
|
||||
{
|
||||
return "`".str_replace("`", "``", $name)."`";
|
||||
}
|
||||
|
||||
function quote($value)
|
||||
{
|
||||
if ($value === NULL)
|
||||
return "NULL";
|
||||
return "'" . $this->link->real_escape_string($s) . "'";
|
||||
}
|
||||
|
||||
function query($sql, $fetchMode = MYSQLI_STORE_RESULT)
|
||||
{
|
||||
$this->queryCount++;
|
||||
if ($this->queryLogFile)
|
||||
{
|
||||
file_put_contents($this->queryLogFile, date("[Y-m-d H:i:s] ").$sql."\n", FILE_APPEND);
|
||||
}
|
||||
return $this->link->query($sql, $fetchMode);
|
||||
}
|
||||
|
||||
function where_builder($where)
|
||||
{
|
||||
if (!is_array($where))
|
||||
return $where;
|
||||
$wh = array();
|
||||
foreach ($where as $k => $v)
|
||||
{
|
||||
if (ctype_digit($k))
|
||||
$wh[] = $v;
|
||||
elseif (is_array($v))
|
||||
{
|
||||
if (!$v)
|
||||
{
|
||||
throw new DatabaseException(E_DB_EMPTY_IN, "Error: empty array for '$k IN (...)', don't know what to do");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_array($v[0]))
|
||||
foreach ($v as &$l)
|
||||
$l = "(" . implode(",", array_map(array($this, 'quote'), $l)) . ")";
|
||||
else
|
||||
$v = array_map(array($this, 'quote'), $v);
|
||||
$wh[] = "$k IN (" . implode(",", $v) . ")";
|
||||
}
|
||||
}
|
||||
elseif ($v !== NULL)
|
||||
$wh[] = "$k=".$this->quote($v);
|
||||
else
|
||||
$wh[] = "$k IS NULL";
|
||||
}
|
||||
if (!$wh)
|
||||
$where = '1';
|
||||
else
|
||||
$where = '(' . join(') AND (', $wh) . ')';
|
||||
return $where;
|
||||
}
|
||||
|
||||
function select_builder($tables, $fields, $where, $options = NULL)
|
||||
{
|
||||
if (!$options)
|
||||
$options = array();
|
||||
else
|
||||
{
|
||||
foreach ($options as $k => $v)
|
||||
if (ctype_digit($k))
|
||||
$options[$v] = true;
|
||||
}
|
||||
if (is_array($fields))
|
||||
$fields = join(',', $fields);
|
||||
$where = $this->where_builder($where);
|
||||
$tables = $this->tables_builder($tables);
|
||||
$sql = 'SELECT ';
|
||||
if ($options['CALC_FOUND_ROWS'] || $options['SQL_CALC_FOUND_ROWS'])
|
||||
$sql .= 'SQL_CALC_FOUND_ROWS ';
|
||||
if ($options['NO_CACHE'] || $options['SQL_NO_CACHE'])
|
||||
$sql .= 'SQL_NO_CACHE ';
|
||||
elseif ($options['CACHE'] || $options['SQL_CACHE'])
|
||||
$sql .= 'SQL_CACHE ';
|
||||
$sql .= "$fields FROM $tables WHERE $where";
|
||||
if ($g = $options['GROUP BY'])
|
||||
{
|
||||
if (is_array($g))
|
||||
{
|
||||
$g1 = array();
|
||||
foreach ($g as $k => $v)
|
||||
{
|
||||
if (ctype_digit($k))
|
||||
$g1[] = $v;
|
||||
else
|
||||
$g1[] = "$k $v";
|
||||
}
|
||||
$g = join(',', $g1);
|
||||
}
|
||||
$sql .= " GROUP BY $g";
|
||||
}
|
||||
if ($g = $options['ORDER BY'])
|
||||
{
|
||||
if (is_array($g))
|
||||
{
|
||||
$g1 = array();
|
||||
foreach ($g as $k => $v)
|
||||
{
|
||||
if (ctype_digit($k))
|
||||
$g1[] = $v;
|
||||
else
|
||||
$g1[] = "$k $v";
|
||||
}
|
||||
$g = join(',', $g1);
|
||||
}
|
||||
$sql .= " ORDER BY $g";
|
||||
}
|
||||
if ($g = $options['LIMIT'])
|
||||
{
|
||||
if (is_array($g))
|
||||
$g = join(',', $g);
|
||||
if ($g)
|
||||
$sql .= " LIMIT $g";
|
||||
}
|
||||
if ($options['FOR UPDATE'])
|
||||
$sql .= ' FOR UPDATE';
|
||||
elseif ($options['LOCK IN SHARE MODE'])
|
||||
$sql .= ' LOCK IN SHARE MODE';
|
||||
return $sql;
|
||||
}
|
||||
|
||||
function tables_builder($tables)
|
||||
{
|
||||
if (is_array($tables))
|
||||
{
|
||||
$t = '';
|
||||
foreach ($tables as $k => $v)
|
||||
{
|
||||
if (!ctype_digit($k))
|
||||
{
|
||||
if (is_array($v))
|
||||
{
|
||||
$join = substr(strtolower($v[0]), 0, 4);
|
||||
if ($join == 'righ')
|
||||
$join = 'RIGHT';
|
||||
elseif ($join == 'left')
|
||||
$join = 'LEFT';
|
||||
else /* if (!$join || $join == 'inne' || $join == 'join') */
|
||||
$join = 'INNER';
|
||||
if (is_array($v[1])) // nested join (left join (A join B on ...) on ...)
|
||||
$table = '('.$this->tables_builder($v[1]).')';
|
||||
else
|
||||
$table = (isset($this->tableNames[$v[1]]) ? $this->quoteId($this->tableNames[$v[1]]) : $v[1]) . ' ' . $k;
|
||||
if ($t)
|
||||
$t .= " $join JOIN $table ON ".$this->where_builder($v[2]);
|
||||
else
|
||||
$t = $table;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
$v = (isset($this->tableNames[$v]) ? $this->quoteId($this->tableNames[$v]) : $v) . ' ' . $k;
|
||||
}
|
||||
else
|
||||
$v = (isset($this->tableNames[$v]) ? $this->quoteId($this->tableNames[$v]).' '.$v : $v);
|
||||
if ($t)
|
||||
$t .= " INNER JOIN $v";
|
||||
else
|
||||
$t = $v;
|
||||
}
|
||||
$tables = $t;
|
||||
}
|
||||
else
|
||||
$tables = preg_replace_callback('/((?:,|JOIN)\s*`)([^`]+)/s', array($this, 'tables_builder_pregcb1'), $tables);
|
||||
return $tables;
|
||||
}
|
||||
|
||||
function tables_builder_pregcb1($m)
|
||||
{
|
||||
$t = $this->tableNames[$m[2]];
|
||||
if (!$t)
|
||||
$t = $m[2];
|
||||
return $m[1].$t;
|
||||
}
|
||||
|
||||
function select($tables, $fields = '*', $where = 1, $options = NULL, $format = 0)
|
||||
{
|
||||
if (!strcmp(intval($fields), "$fields"))
|
||||
{
|
||||
$sql = $tables;
|
||||
$format = $fields;
|
||||
}
|
||||
else
|
||||
$sql = $this->select_builder($tables, $fields, $where, $options);
|
||||
if ($format & MS_RESULT)
|
||||
return $this->query($sql, MYSQLI_USE_RESULT);
|
||||
if ($format & MS_LIST)
|
||||
$r = $this->get_rows($sql);
|
||||
else
|
||||
$r = $this->get_assocs($sql);
|
||||
if (!$r)
|
||||
$r = array();
|
||||
if ($format & MS_ROW)
|
||||
{
|
||||
if ($format & MS_COL)
|
||||
{
|
||||
if (!count($r))
|
||||
return NULL;
|
||||
$r = $r[0];
|
||||
$k = array_keys($r);
|
||||
$r = $r[$k[0]];
|
||||
}
|
||||
else
|
||||
$r = $r[0];
|
||||
}
|
||||
elseif ($format & MS_COL)
|
||||
{
|
||||
foreach ($r as $i => $v)
|
||||
{
|
||||
if (!$k)
|
||||
{
|
||||
$k = array_keys($v);
|
||||
$k = $k[0];
|
||||
}
|
||||
$r[$i] = $v[$k];
|
||||
}
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
function found_rows()
|
||||
{
|
||||
return $this->select('SELECT FOUND_ROWS()', MS_VALUE);
|
||||
}
|
||||
|
||||
function delete($tables, $where, $options = NULL)
|
||||
{
|
||||
$tables = $this->tables_builder($tables);
|
||||
$where = $this->where_builder($where);
|
||||
$sql = "DELETE FROM $tables WHERE $where";
|
||||
if (is_array($options))
|
||||
{
|
||||
if ($g = $options['LIMIT'])
|
||||
{
|
||||
if (is_array($g))
|
||||
$g = join(',', $g);
|
||||
if ($g)
|
||||
$sql .= " LIMIT $g";
|
||||
}
|
||||
}
|
||||
$this->query($sql);
|
||||
return $this->link->affected_rows;
|
||||
}
|
||||
|
||||
function insert_builder($table, $rows, $onduplicatekey = false)
|
||||
{
|
||||
if ($this->tableNames[$table])
|
||||
$table = $this->tableNames[$table];
|
||||
$key = array_keys($rows[0]);
|
||||
foreach ($rows as &$r)
|
||||
{
|
||||
$rs = array();
|
||||
foreach ($key as &$k)
|
||||
$rs[] = $this->quote($r[$k]);
|
||||
$r = "(".implode(",", $rs).")";
|
||||
}
|
||||
foreach ($key as &$k)
|
||||
if (strpos($k, '`') === false)
|
||||
$k = $this->quoteId($k);
|
||||
$sql = "INSERT INTO $table (".implode(",",$key).") VALUES ".implode(",",$rows);
|
||||
if ($onduplicatekey)
|
||||
{
|
||||
foreach ($key as &$k)
|
||||
$k = "$k=VALUES($k)";
|
||||
$sql .= " ON DUPLICATE KEY UPDATE ".implode(",",$key);
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
function insert_row($table, $row)
|
||||
{
|
||||
$sql = $this->insert_builder($table, array($row));
|
||||
if ($this->query($sql))
|
||||
return $this->link->insert_id;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
function update($table, $rows, $where = NULL, $options = NULL)
|
||||
{
|
||||
if (!$rows)
|
||||
return false;
|
||||
if (is_null($where))
|
||||
{
|
||||
if (!is_array($rows))
|
||||
return false;
|
||||
if (!is_array($rows[0]))
|
||||
$rows = array($rows);
|
||||
$sql = $this->insert_builder($table, $rows, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql = array();
|
||||
if (!is_array($rows))
|
||||
$rows = array($rows);
|
||||
foreach ($rows as $k => $v)
|
||||
{
|
||||
if (!ctype_digit($k))
|
||||
$sql[] = $k.'='.$this->quote($v);
|
||||
else
|
||||
$sql[] = $v;
|
||||
}
|
||||
$where = $this->where_builder($where);
|
||||
$sql = 'UPDATE ' . $this->tables_builder($table) . ' SET ' . implode(', ', $sql) . ' WHERE ' . $where;
|
||||
if (is_array($options))
|
||||
{
|
||||
if ($g = $options['LIMIT'])
|
||||
{
|
||||
if (is_array($g))
|
||||
$g = join(',', $g);
|
||||
if ($g)
|
||||
$sql .= " LIMIT $g";
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->query($sql))
|
||||
return $this->link->affected_rows;
|
||||
return false;
|
||||
}
|
||||
|
||||
function get_rows($sql)
|
||||
{
|
||||
$r = array();
|
||||
if ($res = $this->query($sql))
|
||||
{
|
||||
while ($row = $res->fetch_row())
|
||||
$r[] = $row;
|
||||
$res->free();
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
function get_assocs($sql)
|
||||
{
|
||||
$r = array();
|
||||
if ($res = $this->query($sql))
|
||||
{
|
||||
while ($row = $res->fetch_assoc())
|
||||
$r[] = $row;
|
||||
$res->free();
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue