Browse Source
Multi databases support, #12
Multi databases support, #12
git-svn-id: svn+ssh://code.netmonsters.ru/svn/majestic/branches/evo@113 4cb57b5f-5bbd-dd11-951b-001d605cbbc5master
pzinovkin
15 years ago
8 changed files with 880 additions and 0 deletions
-
67Config.php
-
65model/Db.php
-
229model/DbDriver.php
-
30model/DbExpr.php
-
161model/DbStatement.php
-
135model/Model.php
-
104model/MySQLiDriver.php
-
89model/MySQLiStatement.php
@ -0,0 +1,67 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @copyright NetMonsters <team@netmonsters.ru> |
||||
|
* @link http://netmonsters.ru |
||||
|
* @package Majestic |
||||
|
* @subpackage Model |
||||
|
* @since 2010-02-17 |
||||
|
* @version SVN: $Id$ |
||||
|
* @filesource $URL$ |
||||
|
*/ |
||||
|
|
||||
|
class Config extends ArrayObject |
||||
|
{ |
||||
|
|
||||
|
private static $_instance = null; |
||||
|
|
||||
|
|
||||
|
public function __construct($config = array()) |
||||
|
{ |
||||
|
parent::__construct($config, ArrayObject::ARRAY_AS_PROPS); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return Config |
||||
|
*/ |
||||
|
static public function getInstance() |
||||
|
{ |
||||
|
if (is_null(self::$_instance)) { |
||||
|
self::$_instance = new Config(); |
||||
|
} |
||||
|
return self::$_instance; |
||||
|
} |
||||
|
|
||||
|
static public function get($name) |
||||
|
{ |
||||
|
$instance = self::getInstance(); |
||||
|
if (! $instance->offsetExists($name)) { |
||||
|
throw new Exception('Configuration variable "' . $name . '" undefined'); |
||||
|
} |
||||
|
return $instance->offsetGet($name); |
||||
|
} |
||||
|
|
||||
|
static public function set($name, $value) |
||||
|
{ |
||||
|
if (is_array($value)) { |
||||
|
$value = new ConfigArray($value); |
||||
|
} |
||||
|
self::getInstance()->offsetSet($name, $value); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
class ConfigArray extends ArrayObject |
||||
|
{ |
||||
|
public function __construct($array) |
||||
|
{ |
||||
|
parent::__construct($array, ArrayObject::ARRAY_AS_PROPS); |
||||
|
} |
||||
|
|
||||
|
public function offsetGet($index) |
||||
|
{ |
||||
|
if (! $this->offsetExists($index)) { |
||||
|
throw new Exception('Configuration variable "' . $index . '" undefined'); |
||||
|
} |
||||
|
return parent::offsetGet($index); |
||||
|
} |
||||
|
} |
@ -0,0 +1,65 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @copyright NetMonsters <team@netmonsters.ru> |
||||
|
* @link http://netmonsters.ru |
||||
|
* @package Majestic |
||||
|
* @subpackage db |
||||
|
* @since 2010-02-16 |
||||
|
* @version SVN: $Id$ |
||||
|
* @filesource $URL$ |
||||
|
*/ |
||||
|
|
||||
|
class Db |
||||
|
{ |
||||
|
|
||||
|
const FETCH_ASSOC = 2; |
||||
|
const FETCH_NUM = 3; |
||||
|
const FETCH_BOTH = 4; |
||||
|
const FETCH_OBJ = 5; |
||||
|
|
||||
|
/** |
||||
|
* Databases connections |
||||
|
* |
||||
|
* @var array |
||||
|
*/ |
||||
|
static protected $connections = array(); |
||||
|
|
||||
|
/** |
||||
|
* Connect to database |
||||
|
* |
||||
|
* @param string $name Database name. If not set 'default' will be used. |
||||
|
* @param array $config Configuration array. |
||||
|
* |
||||
|
* @return DbDriver |
||||
|
*/ |
||||
|
static public function connect($name = null, $config = null) |
||||
|
{ |
||||
|
if ($name === null) { |
||||
|
$name = 'default'; |
||||
|
} |
||||
|
|
||||
|
if (! isset(self::$connections[$name])) { |
||||
|
if (!$config) { |
||||
|
$config = Config::get('databases')->$name; |
||||
|
} |
||||
|
|
||||
|
if (! is_array($config)) { |
||||
|
throw new Exception('Connection parameters must be an array'); |
||||
|
} |
||||
|
|
||||
|
$driver = 'MySQLiDriver'; |
||||
|
if (isset($config['driver'])) { |
||||
|
$driver = $config['driver']; |
||||
|
unset($config['driver']); |
||||
|
} |
||||
|
|
||||
|
$connection = new $driver($config); |
||||
|
|
||||
|
if (! $connection instanceof DbDriver) { |
||||
|
throw new Exception('Database driver must extends DbDriver'); |
||||
|
} |
||||
|
self::$connections[$name] = $connection; |
||||
|
} |
||||
|
return self::$connections[$name]; |
||||
|
} |
||||
|
} |
@ -0,0 +1,229 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @copyright NetMonsters <team@netmonsters.ru> |
||||
|
* @link http://netmonsters.ru |
||||
|
* @package Majestic |
||||
|
* @subpackage db |
||||
|
* @since 2010-02-16 |
||||
|
* @version SVN: $Id$ |
||||
|
* @filesource $URL$ |
||||
|
*/ |
||||
|
|
||||
|
abstract class DbDriver |
||||
|
{ |
||||
|
|
||||
|
protected $identifier_quote = '`'; |
||||
|
|
||||
|
/** |
||||
|
* Database connection |
||||
|
* |
||||
|
* @var object |
||||
|
*/ |
||||
|
protected $connection = null; |
||||
|
|
||||
|
/** |
||||
|
* Configuration data |
||||
|
* |
||||
|
* @var array |
||||
|
*/ |
||||
|
protected $config = array(); |
||||
|
|
||||
|
|
||||
|
public function __construct($config) |
||||
|
{ |
||||
|
$this->checkConfig($config); |
||||
|
$this->config = $config; |
||||
|
} |
||||
|
|
||||
|
protected function checkConfig($config) |
||||
|
{ |
||||
|
$required = array('database', 'username', 'password', 'hostname'); |
||||
|
foreach ($required as $option) { |
||||
|
if (!isset($config[$option])) { |
||||
|
throw new Exception('Configuration must have a "' . $option . '".'); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public function getConnection() |
||||
|
{ |
||||
|
$this->connect(); |
||||
|
return $this->connection; |
||||
|
} |
||||
|
|
||||
|
public function beginTransaction() |
||||
|
{ |
||||
|
$this->connect(); |
||||
|
$this->driverBeginTransaction(); |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
public function commit() |
||||
|
{ |
||||
|
$this->connect(); |
||||
|
$this->driverCommitTransaction(); |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
public function rollback() |
||||
|
{ |
||||
|
$this->connect(); |
||||
|
$this->driverRollbackTransaction(); |
||||
|
return $this; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param string $sql |
||||
|
* @param mixed $params |
||||
|
* @return DbStatement |
||||
|
*/ |
||||
|
public function query($sql, $params = array()) |
||||
|
{ |
||||
|
$this->connect(); |
||||
|
if (!is_array($params)) { |
||||
|
$params = array($params); |
||||
|
} |
||||
|
$stmt = $this->prepare($sql); |
||||
|
$stmt->execute($params); |
||||
|
return $stmt; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param string $table |
||||
|
* @param mixed $bind |
||||
|
* @return int Affected rows count |
||||
|
*/ |
||||
|
public function insert($table, $bind) |
||||
|
{ |
||||
|
$columns = array(); |
||||
|
foreach ($bind as $col => $val) { |
||||
|
$columns[] = $this->quoteIdentifier($col); |
||||
|
} |
||||
|
$values = array_values($bind); |
||||
|
|
||||
|
$sql = 'INSERT INTO ' . $this->quoteIdentifier($table) |
||||
|
. ' (' . implode(', ', $columns) . ') VALUES (' . $this->quote($values) . ')'; |
||||
|
return $this->query($sql)->affectedRows(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param string $table |
||||
|
* @param array $bind |
||||
|
* @param mixed $where |
||||
|
* @return int |
||||
|
*/ |
||||
|
public function update($table, $bind, $where = '') |
||||
|
{ |
||||
|
$set = array(); |
||||
|
foreach ($bind as $col => $val) { |
||||
|
$set[] = $this->quoteIdentifier($col) . '=' . $this->quote($val); |
||||
|
} |
||||
|
$where = $this->whereExpr($where); |
||||
|
$sql = 'UPDATE ' . $this->quoteIdentifier($table) . ' SET ' . implode(', ', $set) |
||||
|
. (($where) ? (' WHERE ' . $where) : ''); |
||||
|
return $this->query($sql)->affectedRows(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param string $table |
||||
|
* @param mixed $where |
||||
|
* @return int |
||||
|
*/ |
||||
|
public function delete($table, $where = '') |
||||
|
{ |
||||
|
$where = $this->whereExpr($where); |
||||
|
$sql = 'DELETE FROM ' . $this->quoteIdentifier($table) . (($where) ? (' WHERE ' . $where) : ''); |
||||
|
return $this->query($sql)->affectedRows(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param mixed $value |
||||
|
* @return string |
||||
|
*/ |
||||
|
public function quote($value) |
||||
|
{ |
||||
|
if ($value instanceof DbExpr) { |
||||
|
return (string) $value; |
||||
|
} |
||||
|
if (is_array($value)) { |
||||
|
foreach ($value as &$val) { |
||||
|
$val = $this->quote($val); |
||||
|
} |
||||
|
return implode(', ', $value); |
||||
|
} |
||||
|
return $this->driverQuote($value); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param string $ident |
||||
|
* @return string |
||||
|
*/ |
||||
|
public function quoteIdentifier($ident) |
||||
|
{ |
||||
|
$ident = explode('.', $ident); |
||||
|
if (!is_array($ident)) { |
||||
|
$ident = array($ident); |
||||
|
} |
||||
|
foreach ($ident as &$segment) { |
||||
|
$segment = $this->identifier_quote . $segment . $this->identifier_quote; |
||||
|
} |
||||
|
return implode('.', $ident); |
||||
|
} |
||||
|
|
||||
|
public function quoteInto($text, $value) |
||||
|
{ |
||||
|
$pos = strpos($text, '?'); |
||||
|
if ($pos === false) { |
||||
|
return $text; |
||||
|
} |
||||
|
return mb_substr($text, 0, $pos) . $this->quote($value) . mb_substr($text, $pos + 1); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param mixed $where |
||||
|
* @return string |
||||
|
*/ |
||||
|
protected function whereExpr($where) |
||||
|
{ |
||||
|
if (empty($where)) { |
||||
|
return $where; |
||||
|
} |
||||
|
|
||||
|
if (!is_array($where)) { |
||||
|
$where = array($where); |
||||
|
} |
||||
|
foreach ($where as $cond => &$term) { |
||||
|
if (is_int($cond)) { |
||||
|
if ($term instanceof DbExpr) { |
||||
|
$term = (string) $term; |
||||
|
} |
||||
|
} else { |
||||
|
$term = $this->quoteInto($cond, $term); |
||||
|
} |
||||
|
} |
||||
|
return implode(' AND ', $where); |
||||
|
} |
||||
|
|
||||
|
/* Abstract methods */ |
||||
|
|
||||
|
/** |
||||
|
* @return DbStatement |
||||
|
*/ |
||||
|
abstract public function prepare($sql); |
||||
|
|
||||
|
abstract public function getInsertId($table = null, $key = null); |
||||
|
|
||||
|
abstract public function isConnected(); |
||||
|
|
||||
|
abstract public function disconnect(); |
||||
|
|
||||
|
abstract protected function connect(); |
||||
|
|
||||
|
abstract protected function driverQuote($value); |
||||
|
|
||||
|
abstract protected function driverBeginTransaction(); |
||||
|
|
||||
|
abstract protected function driverCommitTransaction(); |
||||
|
|
||||
|
abstract protected function driverRollbackTransaction(); |
||||
|
} |
@ -0,0 +1,30 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @copyright NetMonsters <team@netmonsters.ru> |
||||
|
* @link http://netmonsters.ru |
||||
|
* @package Majestic |
||||
|
* @subpackage db |
||||
|
* @since 2010-02-19 |
||||
|
* @version SVN: $Id$ |
||||
|
* @filesource $URL$ |
||||
|
*/ |
||||
|
|
||||
|
class DbExpr |
||||
|
{ |
||||
|
|
||||
|
protected $expression; |
||||
|
|
||||
|
/** |
||||
|
* @param string $expression |
||||
|
* @return DbExpr |
||||
|
*/ |
||||
|
public function __construct($expression) |
||||
|
{ |
||||
|
$this->expression = (string) $expression; |
||||
|
} |
||||
|
|
||||
|
public function __toString() |
||||
|
{ |
||||
|
return $this->expression; |
||||
|
} |
||||
|
} |
@ -0,0 +1,161 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @copyright NetMonsters <team@netmonsters.ru> |
||||
|
* @link http://netmonsters.ru |
||||
|
* @package Majestic |
||||
|
* @subpackage db |
||||
|
* @since 2010-02-19 |
||||
|
* @version SVN: $Id$ |
||||
|
* @filesource $URL$ |
||||
|
*/ |
||||
|
|
||||
|
abstract class DbStatement |
||||
|
{ |
||||
|
|
||||
|
/** |
||||
|
* @var DbDriver |
||||
|
*/ |
||||
|
protected $driver; |
||||
|
|
||||
|
/** |
||||
|
* @var string |
||||
|
*/ |
||||
|
protected $sql; |
||||
|
|
||||
|
protected $map = null; |
||||
|
|
||||
|
protected $params = array(); |
||||
|
|
||||
|
protected $result; |
||||
|
|
||||
|
public function __construct($driver, $sql) |
||||
|
{ |
||||
|
$this->driver = $driver; |
||||
|
$this->sql = $sql; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param mixed $style |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function fetchAll($style = Db::FETCH_OBJ) |
||||
|
{ |
||||
|
$data = array(); |
||||
|
while ($row = $this->fetch($style)) { |
||||
|
$data[] = $row; |
||||
|
} |
||||
|
return $data; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param string $field |
||||
|
*/ |
||||
|
public function fetchField($field) |
||||
|
{ |
||||
|
$row = $this->fetch(Db::FETCH_ASSOC); |
||||
|
if (isset($row[$field])) { |
||||
|
return $row[$field]; |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
public function bindParam($param, &$value) |
||||
|
{ |
||||
|
if ($this->map === null) { |
||||
|
$this->mapPlaceholders(); |
||||
|
} |
||||
|
if (count($this->map) > 0) { |
||||
|
if (!is_string($param) && !is_int($param)) { |
||||
|
throw new Exception('Placeholder must be an array or string'); |
||||
|
} |
||||
|
if (is_object($value) && ! ($value instanceof DbExpr)) { |
||||
|
throw new Exception('Objects excepts DbExpr not allowed.'); |
||||
|
} |
||||
|
if (isset($this->map[$param])) { |
||||
|
$this->params[$param] = &$value; |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param array $params |
||||
|
* @return bool |
||||
|
*/ |
||||
|
public function execute($params = null) |
||||
|
{ |
||||
|
if (is_array($params)) { |
||||
|
foreach ($params as $param => &$value) { |
||||
|
$this->bindParam($param, $value); |
||||
|
} |
||||
|
} |
||||
|
return $this->driverExecute($this->assemble()); |
||||
|
} |
||||
|
|
||||
|
protected function mapPlaceholders() |
||||
|
{ |
||||
|
$matches = array(); |
||||
|
if(preg_match_all('/(\?|:[A-z0-9_]+)/u', $this->sql, $matches, PREG_OFFSET_CAPTURE)) { |
||||
|
$noname = 0; |
||||
|
foreach ($matches[0] as $id=>$match) { |
||||
|
$match[2] = $matches[1][$id][0]; |
||||
|
$name = ($match[2][0] === ':') ? ltrim($match[2], ':') : $noname++; |
||||
|
$this->map[$name]['placeholder'] = $match[0]; |
||||
|
$this->map[$name]['offset'][] = $match[1]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected function assemble() |
||||
|
{ |
||||
|
if (empty($this->map)) { |
||||
|
return $this->sql; |
||||
|
} |
||||
|
|
||||
|
$query = $this->sql; |
||||
|
$placeholders = array(); |
||||
|
foreach($this->map as $name => $place) { |
||||
|
$value = $this->driver->quote($this->params[$name]); |
||||
|
foreach ($place['offset'] as $offset) { |
||||
|
$placeholders[$offset] = array('placeholder' => $place['placeholder'], 'value' => $value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
ksort($placeholders); |
||||
|
|
||||
|
$increment = 0; |
||||
|
foreach($placeholders as $current_offset => $placeholder) { |
||||
|
$offset = $current_offset + $increment; |
||||
|
$length = mb_strlen($placeholder['placeholder']); |
||||
|
$query = mb_substr($query, 0, $offset) . $placeholder['value'] . mb_substr($query, $offset + $length); |
||||
|
$increment = (($increment - $length) + mb_strlen($placeholder['value'])); |
||||
|
} |
||||
|
return $query; |
||||
|
} |
||||
|
|
||||
|
public function __destruct() |
||||
|
{ |
||||
|
$this->close(); |
||||
|
} |
||||
|
|
||||
|
/* Abstract methods */ |
||||
|
|
||||
|
abstract public function fetch($style = Db::FETCH_OBJ); |
||||
|
|
||||
|
abstract public function fetchObject($class = 'stdClass'); |
||||
|
|
||||
|
abstract public function close(); |
||||
|
|
||||
|
/** |
||||
|
* @return int |
||||
|
*/ |
||||
|
abstract public function affectedRows(); |
||||
|
|
||||
|
abstract public function numRows(); |
||||
|
|
||||
|
/** |
||||
|
* @return bool |
||||
|
*/ |
||||
|
abstract protected function driverExecute($sql); |
||||
|
} |
@ -0,0 +1,135 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* Класс модели данных |
||||
|
* |
||||
|
* @copyright NetMonsters <team@netmonsters.ru> |
||||
|
* @link http://netmonsters.ru |
||||
|
* @package Majestic |
||||
|
* @subpackage Model |
||||
|
* @since 2010-02-16 |
||||
|
* @version SVN: $Id$ |
||||
|
* @filesource $URL$ |
||||
|
*/ |
||||
|
|
||||
|
abstract class Model |
||||
|
{ |
||||
|
|
||||
|
/** |
||||
|
* DbDriver instance |
||||
|
* |
||||
|
* @var DbDriver |
||||
|
*/ |
||||
|
protected $db; |
||||
|
|
||||
|
protected $cache; |
||||
|
|
||||
|
protected $table; |
||||
|
|
||||
|
protected $connection = 'default'; |
||||
|
|
||||
|
protected $key = 'id'; |
||||
|
|
||||
|
public function __construct() |
||||
|
{ |
||||
|
$this->db = Db::connect($this->connection); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return int |
||||
|
*/ |
||||
|
public function getInsertId() |
||||
|
{ |
||||
|
return $this->db->getInsertId($this->table(), $this->key); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param string $ident |
||||
|
* @return string Quoted identifier. |
||||
|
*/ |
||||
|
public function identify($ident) |
||||
|
{ |
||||
|
return $this->db->quoteIdentifier($ident); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param mixed $value |
||||
|
* @return string Quoted value. |
||||
|
*/ |
||||
|
public function quote($value) |
||||
|
{ |
||||
|
return $this->db->quote($value); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param int $id |
||||
|
* @return object |
||||
|
*/ |
||||
|
public function get($id) |
||||
|
{ |
||||
|
$sql = 'SELECT * FROM ' . $this->identify($this->table()) |
||||
|
. ' WHERE ' . $this->identify($this->key) . '=' . (int) $id; |
||||
|
return $this->db->query($sql)->fetch(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param array $data |
||||
|
* @return int Affect row or id of inserted field. |
||||
|
*/ |
||||
|
public function save($data) |
||||
|
{ |
||||
|
$key = isset($data[$this->key]) ? $data[$this->key] : false; |
||||
|
$result = false; |
||||
|
if ($key) { |
||||
|
unset($data[$this->key]); |
||||
|
$result = $this->update($data, $this->identify($this->key) . '=' . (int) $id); |
||||
|
} else { |
||||
|
$result = $this->insert($data); |
||||
|
} |
||||
|
return $result; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param array $data |
||||
|
* @return int Id of inserted row |
||||
|
*/ |
||||
|
public function insert($data) |
||||
|
{ |
||||
|
if (! $this->db->insert($this->table(), $data)) { |
||||
|
return false; |
||||
|
} |
||||
|
return $this->getInsertId(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param array $data |
||||
|
* @param mixed $where |
||||
|
* @return int Number of affected rows |
||||
|
*/ |
||||
|
public function update($data, $where) |
||||
|
{ |
||||
|
return $this->db->update($this->table(), $data, $where); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param mixed $where |
||||
|
* @return int Number of affected rows |
||||
|
*/ |
||||
|
public function delete($where) |
||||
|
{ |
||||
|
if (is_int($where)) { |
||||
|
$where = $this->identify($this->key) . '=' . (int) $where; |
||||
|
} |
||||
|
return $this->db->delete($this->table(), $where); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return string |
||||
|
*/ |
||||
|
public function table() |
||||
|
{ |
||||
|
if (! $this->table) { |
||||
|
$this->table = rtrim(strtolower(get_class($this)), 'model'); |
||||
|
} |
||||
|
return $this->table; |
||||
|
} |
||||
|
} |
@ -0,0 +1,104 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @copyright NetMonsters <team@netmonsters.ru> |
||||
|
* @link http://netmonsters.ru |
||||
|
* @package Majestic |
||||
|
* @subpackage db |
||||
|
* @since 2010-02-17 |
||||
|
* @version SVN: $Id$ |
||||
|
* @filesource $URL$ |
||||
|
*/ |
||||
|
|
||||
|
/** |
||||
|
* @property MySQLi $connection |
||||
|
*/ |
||||
|
class MySQLiDriver extends DbDriver |
||||
|
{ |
||||
|
|
||||
|
/** |
||||
|
* @param mixed $sql |
||||
|
* @return DbStatement |
||||
|
*/ |
||||
|
public function prepare($sql) |
||||
|
{ |
||||
|
return new MySQLiStatement($this, $sql); |
||||
|
} |
||||
|
|
||||
|
public function getInsertId($table = null, $key = null) |
||||
|
{ |
||||
|
return $this->connection->insert_id; |
||||
|
} |
||||
|
|
||||
|
public function isConnected() |
||||
|
{ |
||||
|
return ($this->connection instanceof MySQLi); |
||||
|
} |
||||
|
|
||||
|
public function disconnect() |
||||
|
{ |
||||
|
if ($this->isConnected()) { |
||||
|
$this->connection->close(); |
||||
|
} |
||||
|
$this->connection = null; |
||||
|
} |
||||
|
|
||||
|
protected function connect() |
||||
|
{ |
||||
|
if ($this->connection) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
$port = isset($this->config['port']) ? (int) $this->config['port'] : null; |
||||
|
$this->connection = mysqli_init(); |
||||
|
$connected = @mysqli_real_connect($this->connection, |
||||
|
$this->config['hostname'], |
||||
|
$this->config['username'], |
||||
|
$this->config['password'], |
||||
|
$this->config['database'], |
||||
|
$port); |
||||
|
// Connection errors check
|
||||
|
if (mysqli_connect_error()) { |
||||
|
throw new Exception(mysqli_connect_error(), mysqli_connect_errno()); |
||||
|
} |
||||
|
|
||||
|
$charset = (!empty($this->config['charset'])) ? $this->config['charset'] : 'utf8'; |
||||
|
$this->connection->set_charset($charset); |
||||
|
} |
||||
|
|
||||
|
protected function driverQuote($value) |
||||
|
{ |
||||
|
if (is_int($value) || is_float($value)) { |
||||
|
return $value; |
||||
|
} |
||||
|
|
||||
|
if (is_bool($value)) { |
||||
|
var_dump($value); |
||||
|
return (int) $value; |
||||
|
} |
||||
|
|
||||
|
if ($value === null) { |
||||
|
return 'NULL'; |
||||
|
} |
||||
|
|
||||
|
$this->connect(); |
||||
|
return '\'' . $this->connection->real_escape_string($value) . '\''; |
||||
|
} |
||||
|
|
||||
|
protected function driverBeginTransaction() |
||||
|
{ |
||||
|
$this->connect(); |
||||
|
$this->connection->autocommit(false); |
||||
|
} |
||||
|
|
||||
|
protected function driverCommitTransaction() |
||||
|
{ |
||||
|
$this->connection->commit(); |
||||
|
$this->connection->autocommit(true); |
||||
|
} |
||||
|
|
||||
|
protected function driverRollbackTransaction() |
||||
|
{ |
||||
|
$this->connection->rollback(); |
||||
|
$this->connection->autocommit(true); |
||||
|
} |
||||
|
} |
@ -0,0 +1,89 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @copyright NetMonsters <team@netmonsters.ru> |
||||
|
* @link http://netmonsters.ru |
||||
|
* @package Majestic |
||||
|
* @subpackage db |
||||
|
* @since 2010-02-19 |
||||
|
* @version SVN: $Id$ |
||||
|
* @filesource $URL$ |
||||
|
*/ |
||||
|
|
||||
|
/** |
||||
|
* @property MySQLiDriver $driver |
||||
|
* @property MySQLi_Result $result |
||||
|
*/ |
||||
|
class MySQLiStatement extends DbStatement |
||||
|
{ |
||||
|
|
||||
|
public function fetch($style = Db::FETCH_OBJ) |
||||
|
{ |
||||
|
if (! $this->result) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
$row = false; |
||||
|
switch ($style) { |
||||
|
case Db::FETCH_OBJ: |
||||
|
$row = $this->result->fetch_object(); |
||||
|
break; |
||||
|
case Db::FETCH_NUM: |
||||
|
$row = $this->result->fetch_array(MYSQLI_NUM); |
||||
|
break; |
||||
|
case Db::FETCH_ASSOC: |
||||
|
$row = $this->result->fetch_assoc(); |
||||
|
break; |
||||
|
case Db::FETCH_BOTH: |
||||
|
$row = $this->result->fetch_array(MYSQLI_BOTH); |
||||
|
break; |
||||
|
default: |
||||
|
throw new Exception('Invalid fetch mode "' . $style . '" specified'); |
||||
|
} |
||||
|
return $row; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param string $class |
||||
|
*/ |
||||
|
public function fetchObject($class = 'stdClass') |
||||
|
{ |
||||
|
return $this->result->fetch_object($class); |
||||
|
} |
||||
|
|
||||
|
public function close() |
||||
|
{ |
||||
|
if ($this->result !== null) { |
||||
|
$this->result->close(); |
||||
|
$this->result = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public function affectedRows() |
||||
|
{ |
||||
|
return $this->driver->getConnection()->affected_rows; |
||||
|
} |
||||
|
|
||||
|
public function numRows() |
||||
|
{ |
||||
|
if ($this->result) { |
||||
|
return $this->result->num_rows; |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
protected function driverExecute($sql) |
||||
|
{ |
||||
|
/** |
||||
|
* @var MySQLi |
||||
|
*/ |
||||
|
$mysqli = $this->driver->getConnection(); |
||||
|
$result = $mysqli->query($sql); |
||||
|
if ($result === false) { |
||||
|
throw new Exception($mysqli->error, $mysqli->errno); |
||||
|
} |
||||
|
if ($result instanceof MySQLi_Result) { |
||||
|
$this->result = $result; |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue