You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

294 lines
6.8 KiB

  1. <?php
  2. /**
  3. * Класс модели данных
  4. *
  5. * @copyright NetMonsters <team@netmonsters.ru>
  6. * @link http://netmonsters.ru
  7. * @package Majestic
  8. * @subpackage Model
  9. * @since 2010-02-16
  10. * @version SVN: $Id$
  11. * @filesource $URL$
  12. */
  13. abstract class Model
  14. {
  15. /**
  16. * DbDriver instance
  17. *
  18. * @var DbDriver
  19. */
  20. protected $db;
  21. /**
  22. * Cache instance
  23. *
  24. * @var Cache
  25. */
  26. protected $cache;
  27. /**
  28. * Custom expiration time for keys
  29. *
  30. * @var mixed
  31. */
  32. protected $cache_keys = array();
  33. /**
  34. * Caches to clean.
  35. *
  36. * @var mixed
  37. */
  38. protected $caches_clean = array();
  39. protected $table;
  40. protected $key = 'id';
  41. public function __construct($connection = 'default')
  42. {
  43. $this->db = Db::connect($connection);
  44. }
  45. /**
  46. * @return int
  47. */
  48. public function getInsertId()
  49. {
  50. return $this->db->getInsertId($this->table(), $this->key);
  51. }
  52. /**
  53. * @param string $ident
  54. * @return string Quoted identifier.
  55. */
  56. public function identify($ident)
  57. {
  58. return $this->db->quoteIdentifier($ident);
  59. }
  60. /**
  61. * @param mixed $value
  62. * @return string Quoted value.
  63. */
  64. public function quote($value)
  65. {
  66. return $this->db->quote($value);
  67. }
  68. /**
  69. * @param int $id
  70. * @return object
  71. */
  72. public function get($id)
  73. {
  74. $sql = 'SELECT * FROM :table WHERE :pk=?';
  75. return $this->fetch($sql, $id);
  76. }
  77. /**
  78. * @param array $data
  79. * @param array $on_duplicate
  80. * @return int Id of inserted row
  81. */
  82. public function insert($data, $on_duplicate = array())
  83. {
  84. $affected = $this->db->insert($this->table(), $data, $on_duplicate);
  85. return ($this->getInsertId()) ? $this->getInsertId() : $affected;
  86. }
  87. /**
  88. * @param array $data
  89. * @param mixed $where
  90. * @return int Number of affected rows
  91. */
  92. public function update($data, $where)
  93. {
  94. if (is_int($where) || $where === (string) (int) $where) {
  95. $where = $this->identify($this->key) . '=' . (int) $where;
  96. }
  97. return $this->db->update($this->table(), $data, $where);
  98. }
  99. /**
  100. * @param int $id Int id
  101. * @return int Number of affected rows
  102. */
  103. public function delete($id)
  104. {
  105. $where = $this->identify($this->key) . '=' . (int) $id;
  106. return $this->db->delete($this->table(), $where);
  107. }
  108. /**
  109. * @return string
  110. */
  111. protected function table()
  112. {
  113. if (!$this->table) {
  114. $this->table = substr(strtolower(get_class($this)), 0, -5/*strlen('Model')*/);
  115. }
  116. return $this->table;
  117. }
  118. /**
  119. * Creates order sql string
  120. *
  121. * @param array $params
  122. * @param array $sortable
  123. * @return string
  124. */
  125. protected function order($params, $sortable = array('id'))
  126. {
  127. $sql = '';
  128. if (isset($params['sort'])) {
  129. $order = (isset($params['order']) && $params['order'] == 'desc') ? 'DESC' : 'ASC';
  130. if (in_array($params['sort'], $sortable)) {
  131. $sql = ' ORDER BY ' . $this->identify($params['sort']) . ' ' . $order;
  132. }
  133. }
  134. return $sql;
  135. }
  136. /**
  137. * Searches using like
  138. *
  139. * @param array $params
  140. * @param array $searchable
  141. * @param string $table_prefix
  142. * @return string
  143. */
  144. protected function search($params, $searchable = array('id'), $table_prefix = '')
  145. {
  146. $sql = '';
  147. if (isset($params['q']) && isset($params['qt']) && in_array($params['qt'], $searchable)) {
  148. if ($table_prefix) {
  149. $sql = $table_prefix . '.';
  150. }
  151. $sql .= $this->identify($params['qt']) . ' LIKE ' . $this->quote('%' . $params['q'] . '%');
  152. }
  153. return $sql;
  154. }
  155. /**
  156. * This method appends to params table and primary key.
  157. * So they can be accessed thru `:table` and `:pk` placeholders.
  158. *
  159. * @return DbStatement
  160. */
  161. protected function query($sql, $params = array())
  162. {
  163. if (!is_array($params)) {
  164. $params = array($params);
  165. }
  166. $params = array(
  167. 'table' => new DbExpr($this->identify($this->table())),
  168. 'pk' => new DbExpr($this->identify($this->key)),
  169. ) + $params;
  170. return $this->db->query($sql, $params);
  171. }
  172. /**
  173. * @param string $sql
  174. * @param array $params
  175. * @param string $field
  176. * @param CacheKey $cache_key
  177. */
  178. protected function fetchField($sql, $params = array(), $field, $cache_key = null)
  179. {
  180. if (!$cache_key || !$result = $cache_key->get()) {
  181. $result = $this->query($sql, $params)->fetchField($field);
  182. if ($cache_key) {
  183. $cache_key->set($result);
  184. }
  185. }
  186. return $result;
  187. }
  188. /**
  189. * @param string $sql
  190. * @param array $params
  191. * @param CacheKey $cache_key
  192. */
  193. protected function fetch($sql, $params = array(), $cache_key = null)
  194. {
  195. if (!$cache_key || !$result = $cache_key->get()) {
  196. $result = $this->query($sql, $params)->fetch();
  197. if ($cache_key) {
  198. $cache_key->set($result);
  199. }
  200. }
  201. // $debug = __CLASS__;
  202. $debug = get_class($this->query($sql, $params));
  203. // $debug = get_class_methods($this->query($sql, $params));
  204. //$result = print_r($debug, true);
  205. return $result;
  206. }
  207. /**
  208. * @param string $sql
  209. * @param array $params
  210. * @param CacheKey $cache_key
  211. */
  212. protected function fetchAll($sql, $params = array(), $cache_key = null)
  213. {
  214. if (!$cache_key || !$result = $cache_key->get()) {
  215. $result = $this->query($sql, $params)->fetchAll();
  216. if ($cache_key) {
  217. $cache_key->set($result);
  218. }
  219. }
  220. return $result;
  221. }
  222. /* Cache workaround */
  223. /**
  224. * @return Cache
  225. */
  226. public function getCache()
  227. {
  228. if (!$this->cache) {
  229. $this->cache = Cacher::get(Config::get(__CLASS__, 'MemcacheCache'));
  230. }
  231. return $this->cache;
  232. }
  233. /**
  234. * @param string $name
  235. * @param array $params
  236. * @return CacheKey
  237. */
  238. protected function cacheKey($name, $params = array())
  239. {
  240. $expire = (isset($this->cache_keys[$name])) ? ($this->cache_keys[$name] * 60) : 0;
  241. return new CacheKey($this->getCache(), $name, $params, $expire);
  242. }
  243. /**
  244. * @param CacheKey $cache
  245. */
  246. protected function addCleanCache($cache)
  247. {
  248. $this->caches_clean[] = $cache;
  249. }
  250. protected function cleanCaches()
  251. {
  252. // cleaning caches
  253. foreach ($this->caches_clean as $cache) {
  254. $cache->del();
  255. }
  256. $this->caches_clean = array();
  257. }
  258. }