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.

235 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 2011-11-11
  10. */
  11. /**
  12. * @property SqlDbDriver $db
  13. */
  14. abstract class SqlModel extends Model
  15. {
  16. /**
  17. * @param string $ident
  18. * @return string Quoted identifier.
  19. */
  20. public function identify($ident)
  21. {
  22. return $this->db->quoteIdentifier($ident);
  23. }
  24. /**
  25. * @param mixed $value
  26. * @return string Quoted value.
  27. */
  28. public function quote($value)
  29. {
  30. return $this->db->quote($value);
  31. }
  32. /**
  33. * @param int $id
  34. * @return object
  35. */
  36. public function get($id)
  37. {
  38. $sql = 'SELECT * FROM :table WHERE :pk=?';
  39. return $this->fetch($sql, $id);
  40. }
  41. /**
  42. * @param array $data
  43. * @param mixed $where
  44. * @return int Number of affected rows
  45. */
  46. public function update($data, $where)
  47. {
  48. if (is_int($where) || $where === (string) (int) $where) {
  49. $where = $this->identify($this->key) . '=' . (int) $where;
  50. }
  51. return parent::update($data, $where);
  52. }
  53. /**
  54. * @param int $id Int id
  55. * @return int Number of affected rows
  56. */
  57. public function delete($id)
  58. {
  59. $where = $this->identify($this->key) . '=' . (int) $id;
  60. return $this->db->delete($this->table(), $where);
  61. }
  62. /**
  63. * Creates order sql string
  64. *
  65. * @param array $params
  66. * @param array $sortable
  67. * @return string
  68. */
  69. protected function order($params, $sortable = array('id'))
  70. {
  71. $sql = '';
  72. if (isset($params['sort'])) {
  73. if (!is_array($params['sort'])) {
  74. if (isset($params['order'])) {
  75. $params['order'] = array($params['sort'] => $params['order']);
  76. }
  77. $params['sort'] = array($params['sort']);
  78. }
  79. $order_list = array();
  80. for ($i = 0; $i < count($params['sort']); $i++) {
  81. $order = (isset($params['order'][$params['sort'][$i]]) && $params['order'][$params['sort'][$i]] == 'desc') ? 'DESC' : 'ASC';
  82. if (in_array($params['sort'][$i], $sortable)) {
  83. $order_list[] = $this->identify($params['sort'][$i]) . ' ' . $order;
  84. }
  85. }
  86. if ($order_list) {
  87. $sql = ' ORDER BY ' . implode(',', $order_list);
  88. }
  89. }
  90. return $sql;
  91. }
  92. /**
  93. * Searches using like
  94. *
  95. * @param array $params
  96. * @param array $searchable
  97. * @param string $table_prefix
  98. * @return string
  99. */
  100. protected function search($params, $searchable = array('id'), $table_prefix = '')
  101. {
  102. $sql = '';
  103. if (isset($params['q']) && isset($params['qt']) && in_array($params['qt'], $searchable)) {
  104. if ($table_prefix) {
  105. $sql = $table_prefix . '.';
  106. }
  107. $sql .= $this->identify($params['qt']) . ' LIKE ' . $this->quote('%' . $params['q'] . '%');
  108. }
  109. return $sql;
  110. }
  111. /**
  112. * This method appends to params table and primary key.
  113. * So they can be accessed through `:table` and `:pk` placeholders.
  114. *
  115. * @param string $sql
  116. * @param array $params
  117. * @return DbStatement
  118. */
  119. protected function query($sql, $params = array())
  120. {
  121. if (!is_array($params)) {
  122. $params = array($params);
  123. }
  124. $params = array(
  125. 'table' => new DbExpr($this->identify($this->table())),
  126. 'pk' => new DbExpr($this->identify($this->key)),
  127. ) + $params;
  128. return $this->db->query($sql, $params);
  129. }
  130. /**
  131. * @param string $data Request
  132. * @param array $params Request parameters
  133. * @param string $field Requested field name
  134. * @param CacheKey $cache_key Key for caching in
  135. * @return mixed
  136. */
  137. protected function fetchField($data, $params = array(), $field, $cache_key = null)
  138. {
  139. if (!$cache_key || !$result = $cache_key->get()) {
  140. $result = $this->query($data, $params)->fetchField($field);
  141. if ($cache_key) {
  142. $cache_key->set($result);
  143. }
  144. }
  145. return $result;
  146. }
  147. /**
  148. * @param string $data Request
  149. * @param array $params Request parameters
  150. * @param CacheKey $cache_key Key for caching in
  151. * @return mixed
  152. */
  153. protected function fetch($data, $params = array(), $cache_key = null)
  154. {
  155. if (!$cache_key || !$result = $cache_key->get()) {
  156. $result = $this->query($data, $params)->fetch();
  157. if ($cache_key) {
  158. $cache_key->set($result);
  159. }
  160. }
  161. return $result;
  162. }
  163. /**
  164. * @param string $data
  165. * @param array $params
  166. * @param CacheKey $cache_key
  167. * @return array
  168. */
  169. protected function fetchAll($data, $params = array(), $cache_key = null)
  170. {
  171. if (!$cache_key || !$result = $cache_key->get()) {
  172. $result = $this->query($data, $params)->fetchAll();
  173. if ($cache_key) {
  174. $cache_key->set($result);
  175. }
  176. }
  177. return $result;
  178. }
  179. public function find($select, $distinct, $where, $order, $limit)
  180. {
  181. if (!$select) {
  182. $select = array(new DbExpr('*'));
  183. }
  184. foreach ($select as $field => &$term) {
  185. if (is_int($field)) {
  186. if ($term instanceof DbExpr) {
  187. $term = (string) $term;
  188. } else {
  189. $term = $this->db->quoteIdentifier($term);
  190. }
  191. } else {
  192. $term = $this->db->quoteIdentifier($field) . ' as ' . $this->db->quoteIdentifier($term);
  193. }
  194. }
  195. foreach ($where as $cond => &$term) {
  196. if (is_array($term)) {
  197. $term = new DbExpr('(' . implode(',', array_map(function($item){return intval($item);}, $term)) . ')');
  198. }
  199. $term = $this->db->quoteInto($cond, $term);
  200. }
  201. if ($distinct != '') {
  202. $distinct = 'DISTINCT ' . $this->db->quoteIdentifier($distinct);
  203. }
  204. if ($limit != '') {
  205. $limit = implode(',',array_map(function($item){return intval($item);},explode(',',$limit)));
  206. }
  207. $result_items = parent::fetchAll('SELECT ' . (($distinct) ? $distinct : implode(',', $select))
  208. . ' FROM ' . $this->table()
  209. . (($where) ? (' WHERE ' . implode(' AND ', $where)) : '')
  210. . (($order) ? ($this->order($order, $order['sort'])) : '')
  211. . (($limit) ? (' LIMIT ' . $limit) : ''));
  212. return new SqlResultProvider($result_items);
  213. }
  214. /**
  215. * @return SqlCriteria
  216. */
  217. public function criteria()
  218. {
  219. return new SqlCriteria();
  220. }
  221. }