Anton Grebnev
13 years ago
14 changed files with 589 additions and 334 deletions
-
1.gitignore
-
171model/DbDriver.php
-
197model/Model.php
-
77model/MongoDriver.php
-
2model/MySQLiDriver.php
-
13model/NoSqlDbDriver.php
-
185model/SqlDbDriver.php
-
173model/SqlModel.php
-
BINmodel_class_diadram.png
-
65tests/model/MongoDriverTest.php
-
1tests/model/MySQLiDriverTest.php
-
9tests/model/SqlDbDriverTest.php
-
23tests/model/SqlModelTest.php
-
BINuml_model.zargo
@ -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); |
||||
|
} |
||||
|
} |
||||
|
|
@ -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); |
||||
|
} |
@ -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(); |
||||
|
|
||||
|
} |
||||
|
|
@ -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; |
||||
|
} |
||||
|
|
||||
|
} |
After Width: 1743 | Height: 1107 | Size: 42 KiB |
@ -0,0 +1,65 @@ |
|||||
|
<?php |
||||
|
|
||||
|
/* |
||||
|
* @copyright NetMonsters <team@netmonsters.ru> |
||||
|
* @link http://netmonsters.ru |
||||
|
* @package Majestic |
||||
|
* @subpackage UnitTests |
||||
|
* @since 2011-11-10 |
||||
|
* |
||||
|
* Unit tests for MongoDriver class |
||||
|
*/ |
||||
|
|
||||
|
require_once dirname(__FILE__) . '/../../model/DbDriver.php'; |
||||
|
require_once dirname(__FILE__) . '/../../model/NoSqlDbDriver.php'; |
||||
|
require_once dirname(__FILE__) . '/../../model/MongoDriver.php'; |
||||
|
|
||||
|
class MongoDriverTest extends PHPUnit_Framework_TestCase |
||||
|
{ |
||||
|
|
||||
|
private $conf = array(); |
||||
|
|
||||
|
public function setUp() |
||||
|
{ |
||||
|
$this->conf = array( |
||||
|
'hostname' => 'localhost', |
||||
|
'database' => 'test', |
||||
|
'username' => 'test', |
||||
|
'password' => '1234', |
||||
|
'port' => 27017 |
||||
|
); |
||||
|
} |
||||
|
/** |
||||
|
* @expectedException Exception |
||||
|
* @expectedExceptionMessage Configuration must have a "hostname". |
||||
|
*/ |
||||
|
public function testGetConnectionNoHostname() |
||||
|
{ |
||||
|
unset($this->conf['hostname']); |
||||
|
$mongo = new MongoDriver($this->conf); |
||||
|
$mongo->getConnection(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @expectedException MongoConnectionException |
||||
|
* @expectedExceptionMessage Couldn't authenticate with database |
||||
|
*/ |
||||
|
public function testGetConnectionWrongPassword() |
||||
|
{ |
||||
|
$this->conf['password'] = 'nopass'; |
||||
|
$mongo = new MongoDriver($this->conf); |
||||
|
$this->assertInstanceOf('Mongo', $mongo->getConnection()); |
||||
|
} |
||||
|
|
||||
|
public function testGetConnection() |
||||
|
{ |
||||
|
$mongo = new MongoDriver($this->conf); |
||||
|
|
||||
|
$this->assertFalse($mongo->isConnected()); |
||||
|
$this->assertInstanceOf('Mongo', $mongo->getConnection()); |
||||
|
$this->assertTrue($mongo->isConnected()); |
||||
|
$mongo->disconnect(); |
||||
|
$this->assertFalse($mongo->isConnected()); |
||||
|
} |
||||
|
|
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue