rebuild Model package for NoSQL drivers

This commit is contained in:
Anton Grebnev
2011-11-11 18:01:17 +04:00
parent 6aab56c814
commit 3c5a5d9603
14 changed files with 589 additions and 334 deletions

View File

@ -12,8 +12,6 @@
abstract class DbDriver
{
protected $identifier_quote = '`';
/**
* Database connection
*
@ -44,173 +42,20 @@ abstract class DbDriver
}
}
}
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
* @param mixed $on_duplicate
* @return int Affected rows count
*/
public function insert($table, $bind, $on_duplicate = array())
{
$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 = mb_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 */
abstract public function insert($table, $data);
abstract public function update($table, $data, $condition);
/**
* @return DbStatement
*/
abstract public function prepare($sql);
abstract public function delete($table, $condition);
abstract public function getInsertId($table = null, $key = null);
@ -219,12 +64,4 @@ abstract class DbDriver
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();
}

View File

@ -62,41 +62,13 @@ abstract class Model
}
/**
* @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 :table WHERE :pk=?';
return $this->fetch($sql, $id);
}
/**
* @param array $data
* @param array $on_duplicate
* @return int Id of inserted row
*/
public function insert($data, $on_duplicate = array())
public function insert($data)
{
$affected = $this->db->insert($this->table(), $data, $on_duplicate);
$affected = $this->db->insert($this->table(), $data);
return ($this->getInsertId()) ? $this->getInsertId() : $affected;
}
@ -107,21 +79,8 @@ abstract class Model
*/
public function update($data, $where)
{
if (is_int($where) || $where === (string) (int) $where) {
$where = $this->identify($this->key) . '=' . (int) $where;
}
return $this->db->update($this->table(), $data, $where);
}
/**
* @param int $id Int id
* @return int Number of affected rows
*/
public function delete($id)
{
$where = $this->identify($this->key) . '=' . (int) $id;
return $this->db->delete($this->table(), $where);
}
/**
* @return string
@ -133,112 +92,7 @@ abstract class Model
}
return $this->table;
}
/**
* Creates order sql string
*
* @param array $params
* @param array $sortable
* @return string
*/
protected function order($params, $sortable = array('id'))
{
$sql = '';
if (isset($params['sort'])) {
$order = (isset($params['order']) && $params['order'] == 'desc') ? 'DESC' : 'ASC';
if (in_array($params['sort'], $sortable)) {
$sql = ' ORDER BY ' . $this->identify($params['sort']) . ' ' . $order;
}
}
return $sql;
}
/**
* Searches using like
*
* @param array $params
* @param array $searchable
* @param string $table_prefix
* @return string
*/
protected function search($params, $searchable = array('id'), $table_prefix = '')
{
$sql = '';
if (isset($params['q']) && isset($params['qt']) && in_array($params['qt'], $searchable)) {
if ($table_prefix) {
$sql = $table_prefix . '.';
}
$sql .= $this->identify($params['qt']) . ' LIKE ' . $this->quote('%' . $params['q'] . '%');
}
return $sql;
}
/**
* This method appends to params table and primary key.
* So they can be accessed thru `:table` and `:pk` placeholders.
*
* @return DbStatement
*/
protected function query($sql, $params = array())
{
if (!is_array($params)) {
$params = array($params);
}
$params = array(
'table' => new DbExpr($this->identify($this->table())),
'pk' => new DbExpr($this->identify($this->key)),
) + $params;
return $this->db->query($sql, $params);
}
/**
* @param string $sql
* @param array $params
* @param string $field
* @param CacheKey $cache_key
*/
protected function fetchField($sql, $params = array(), $field, $cache_key = null)
{
if (!$cache_key || !$result = $cache_key->get()) {
$result = $this->query($sql, $params)->fetchField($field);
if ($cache_key) {
$cache_key->set($result);
}
}
return $result;
}
/**
* @param string $sql
* @param array $params
* @param CacheKey $cache_key
*/
protected function fetch($sql, $params = array(), $cache_key = null)
{
if (!$cache_key || !$result = $cache_key->get()) {
$result = $this->query($sql, $params)->fetch();
if ($cache_key) {
$cache_key->set($result);
}
}
return $result;
}
/**
* @param string $sql
* @param array $params
* @param CacheKey $cache_key
*/
protected function fetchAll($sql, $params = array(), $cache_key = null)
{
if (!$cache_key || !$result = $cache_key->get()) {
$result = $this->query($sql, $params)->fetchAll();
if ($cache_key) {
$cache_key->set($result);
}
}
return $result;
}
/* Cache workaround */
@ -280,4 +134,51 @@ abstract class Model
}
$this->caches_clean = array();
}
/**
* Abstract methods
*/
/**
* @param int $id
* @return object
*/
abstract public function get($id);
/**
* @param int $id Int id
* @return int Number of affected rows
*/
abstract public function delete($id);
/**
* Creates order sql string
*
* @param array $params
* @param array $sortable
* @return string
*/
abstract protected function order($params, $sortable = array('id'));
/**
* @param string $sql
* @param array $params
* @param string $field
* @param CacheKey $cache_key
*/
abstract protected function fetchField($data, $params = array(), $field, $cache_key = null);
/**
* @param string $sql
* @param array $params
* @param CacheKey $cache_key
*/
abstract protected function fetch($data, $params = array(), $cache_key = null);
/**
* @param string $sql
* @param array $params
* @param CacheKey $cache_key
*/
abstract protected function fetchAll($data, $params = array(), $cache_key = null);
}

77
model/MongoDriver.php Normal file
View File

@ -0,0 +1,77 @@
<?php
/**
* @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru
* @package Majestic
* @subpackage db
* @since 2011-11-10
*/
/**
* @property Mongo $connection
*/
class MongoDriver extends NoSqlDbDriver
{
public function find($data, $params = array(), $cache_key = null)
{
}
public function insert($table, $bind, $on_duplicate = array())
{
return parent::insert($table, $bind, $on_duplicate);
}
public function update($table, $bind, $where = '')
{
return parent::update($table, $bind, $where);
}
public function delete($table, $where = '')
{
return parent::delete($table, $where);
}
public function getInsertId($table = null, $key = null)
{
// TODO: Implement getInsertId() method.
}
public function isConnected()
{
if (!is_null($this->connection)) {
return $this->connection->connected;
} else {
return false;
}
}
public function disconnect()
{
if ($this->isConnected()) {
$this->connection->close();
}
$this->connection = null;
}
protected function connect()
{
if ($this->connection) {
return;
}
$host = $this->config['hostname'];
$port = isset($this->config['port']) ? ':' . (string) $this->config['port'] : '';
$this->config = array(
'username' => $this->config['username'],
'password' => $this->config['password'],
'db' => $this->config['database']
);
$this->connection = new Mongo('mongodb://' . $host . $port, $this->config);
}
}

View File

@ -12,7 +12,7 @@
/**
* @property MySQLi $connection
*/
class MySQLiDriver extends DbDriver
class MySQLiDriver extends SqlDbDriver
{
public function insert($table, $bind, $on_duplicate = array())

13
model/NoSqlDbDriver.php Normal file
View File

@ -0,0 +1,13 @@
<?php
/**
* @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru
* @package Majestic
* @subpackage db
* @since 2011-11-11
*/
abstract class NoSqlDbDriver extends DbDriver
{
abstract function find($data, $params = array(), $cache_key = null);
}

185
model/SqlDbDriver.php Normal file
View File

@ -0,0 +1,185 @@
<?php
/**
* @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru
* @package Majestic
* @subpackage db
* @since 2011-11-11
*/
abstract class SqlDbDriver extends DbDriver
{
protected $identifier_quote = '`';
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
* @param mixed $on_duplicate
* @return int Affected rows count
*/
public function insert($table, $data)
{
$columns = array();
foreach ($data as $col => $val) {
$columns[] = $this->quoteIdentifier($col);
}
$values = array_values($data);
$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, $data, $condition = '')
{
$set = array();
foreach ($data as $col => $val) {
$set[] = $this->quoteIdentifier($col) . '=' . $this->quote($val);
}
$where = $this->whereExpr($condition);
$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, $condition = '')
{
$where = $this->whereExpr($condition);
$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 = mb_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);
}
/**
* @return DbStatement
*/
abstract public function prepare($sql);
abstract protected function driverQuote($value);
abstract protected function driverBeginTransaction();
abstract protected function driverCommitTransaction();
abstract protected function driverRollbackTransaction();
}

173
model/SqlModel.php Normal file
View File

@ -0,0 +1,173 @@
<?php
/**
* Класс модели данных
*
* @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru
* @package Majestic
* @subpackage Model
* @since 2011-11-11
*/
abstract class SqlModel extends Model
{
/**
* @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 :table WHERE :pk=?';
return $this->fetch($sql, $id);
}
/**
* @param array $data
* @param mixed $where
* @return int Number of affected rows
*/
public function update($data, $where)
{
if (is_int($where) || $where === (string) (int) $where) {
$where = $this->identify($this->key) . '=' . (int) $where;
}
return parent::update($data, $where);
}
/**
* @param int $id Int id
* @return int Number of affected rows
*/
public function delete($id)
{
$where = $this->identify($this->key) . '=' . (int) $id;
return $this->db->delete($this->table(), $where);
}
/**
* Creates order sql string
*
* @param array $params
* @param array $sortable
* @return string
*/
protected function order($params, $sortable = array('id'))
{
$sql = '';
if (isset($params['sort'])) {
$order = (isset($params['order']) && $params['order'] == 'desc') ? 'DESC' : 'ASC';
if (in_array($params['sort'], $sortable)) {
$sql = ' ORDER BY ' . $this->identify($params['sort']) . ' ' . $order;
}
}
return $sql;
}
/**
* Searches using like
*
* @param array $params
* @param array $searchable
* @param string $table_prefix
* @return string
*/
protected function search($params, $searchable = array('id'), $table_prefix = '')
{
$sql = '';
if (isset($params['q']) && isset($params['qt']) && in_array($params['qt'], $searchable)) {
if ($table_prefix) {
$sql = $table_prefix . '.';
}
$sql .= $this->identify($params['qt']) . ' LIKE ' . $this->quote('%' . $params['q'] . '%');
}
return $sql;
}
/**
* This method appends to params table and primary key.
* So they can be accessed thru `:table` and `:pk` placeholders.
*
* @return DbStatement
*/
protected function query($sql, $params = array())
{
if (!is_array($params)) {
$params = array($params);
}
$params = array(
'table' => new DbExpr($this->identify($this->table())),
'pk' => new DbExpr($this->identify($this->key)),
) + $params;
return $this->db->query($sql, $params);
}
/**
* @param string $sql
* @param array $params
* @param string $field
* @param CacheKey $cache_key
*/
protected function fetchField($data, $params = array(), $field, $cache_key = null)
{
if (!$cache_key || !$result = $cache_key->get()) {
$result = $this->query($data, $params)->fetchField($field);
if ($cache_key) {
$cache_key->set($result);
}
}
return $result;
}
/**
* @param string $sql
* @param array $params
* @param CacheKey $cache_key
*/
protected function fetch($data, $params = array(), $cache_key = null)
{
if (!$cache_key || !$result = $cache_key->get()) {
$result = $this->query($data, $params)->fetch();
if ($cache_key) {
$cache_key->set($result);
}
}
return $result;
}
/**
* @param string $sql
* @param array $params
* @param CacheKey $cache_key
*/
protected function fetchAll($data, $params = array(), $cache_key = null)
{
if (!$cache_key || !$result = $cache_key->get()) {
$result = $this->query($data, $params)->fetchAll();
if ($cache_key) {
$cache_key->set($result);
}
}
return $result;
}
}