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.

211 lines
6.3 KiB

  1. <?php
  2. class SqlCriteria
  3. {
  4. const JOIN_TYPE_DEFAULT = 100;
  5. const JOIN_TYPE_LEFT = 101;
  6. const JOIN_TYPE_RIGHT = 102;
  7. const JOIN_TYPE_INNER = 103;
  8. const JOIN_TYPE_OUTER = 104;
  9. private static $join_type_to_reserved_keyword = array(
  10. self::JOIN_TYPE_DEFAULT => 'JOIN',
  11. self::JOIN_TYPE_LEFT => 'LEFT JOIN',
  12. self::JOIN_TYPE_RIGHT => 'RIGHT JOIN',
  13. self::JOIN_TYPE_INNER => 'INNER JOIN',
  14. self::JOIN_TYPE_OUTER => 'OUTER JOIN',
  15. );
  16. private $select = array();
  17. private $distinct = '';
  18. private $where = array();
  19. private $group_by = array();
  20. private $order = array('sort' => array(), 'order' => array());
  21. private $limit = '';
  22. /**
  23. * @var SqlModel
  24. */
  25. private $model;
  26. private $sql_expression;
  27. private $sql_expression_params = array();
  28. private $sql_join_expressions = array();
  29. /**
  30. * @param $model SqlModel
  31. * @param $sql_expression string|null Sql expression with SELECT and FROM operators. If fetched, then SqlCriteria::select(), SqlCriteria::distinct() disabled for use.
  32. * @param $sql_expression_params array additional params to be replaced in sql expression
  33. */
  34. public function __construct($model, $sql_expression = null, $sql_expression_params = array())
  35. {
  36. $this->model = $model;
  37. $this->sql_expression = $sql_expression;
  38. $this->sql_expression_params = $sql_expression_params;
  39. }
  40. /**
  41. * @return SqlResultProvider
  42. */
  43. public function find()
  44. {
  45. // preparing link expressions (if exists)
  46. if ($this->sql_join_expressions) {
  47. if (!$this->sql_expression) {
  48. $select = $this->model->getDb()->selectExpr($this->select, $this->distinct);
  49. $this->sql_expression = 'SELECT ' . $select . ' FROM :table';
  50. }
  51. $this->sql_expression .= ' ' . implode(' ', $this->sql_join_expressions);
  52. }
  53. return $this->model->find($this->select, $this->distinct, $this->where, $this->order, $this->limit, null, $this->group_by, $this->sql_expression, $this->sql_expression_params);
  54. }
  55. public function delete()
  56. {
  57. return $this->model->find('', '', $this->where, null, null, null, null, 'DELETE FROM :table', $this->sql_expression_params)->affectedRows();
  58. }
  59. public function count()
  60. {
  61. return $this->model->find(new DbExpr('COUNT(*) as count'), '', $this->where, null, null, null, null, $this->sql_expression, $this->sql_expression_params)->fetchField('count');
  62. }
  63. public function join($join_table_name, $join_field_name, $donor_table_name = null, $donor_field_name = null, $join_type = self::JOIN_TYPE_DEFAULT)
  64. {
  65. $donor_field_name = $donor_field_name ? : $join_field_name;
  66. $donor_table_name = $donor_table_name ? : 'table';
  67. $this->sql_join_expressions[] = self::$join_type_to_reserved_keyword[$join_type]
  68. . ' :' . $join_table_name
  69. . ' ON :' . $donor_table_name . '.' . $donor_field_name . '='
  70. . ':' . $join_table_name . '.' . $join_field_name;
  71. $this->sql_expression_params[$join_table_name] = new DbExpr($this->model->identify($join_table_name));
  72. return $this;
  73. }
  74. /**
  75. * @param $cond string|array Condition with "?" placeholder @ex 'field=?' or 'field=1' or array('field=?' => 1', 'field=1')
  76. * @param $value string|array|DbExpr|null Value. Array transformed to DbExpr(implode(',' Array)) All elements in the array mast be integer
  77. * @return SqlCriteria
  78. * @desc Allow multiple calls
  79. */
  80. public function where($cond, $value = null)
  81. {
  82. if (is_null($value)) {
  83. if (is_array($cond)) {
  84. $this->where = $this->where + $cond;
  85. } else {
  86. $this->where[] = $cond;
  87. }
  88. } else {
  89. $this->where[$cond] = $value;
  90. }
  91. return $this;
  92. }
  93. /**
  94. * @param $field string
  95. * @param $value array
  96. * @return SqlCriteria
  97. */
  98. public function whereIn($field, $value)
  99. {
  100. return $this->where($field . ' in ?', $value);
  101. }
  102. /**
  103. * @param $field string
  104. * @param $value array
  105. * @return SqlCriteria
  106. */
  107. public function whereNotIn($field, $value)
  108. {
  109. return $this->where($field . ' not in ?', $value);
  110. }
  111. /**
  112. * @param $field string
  113. * @param $value array
  114. * @return SqlCriteria
  115. * @deprecated
  116. */
  117. public function whereNot($field, $value)
  118. {
  119. return $this->whereNotIn($field, $value);
  120. }
  121. public function groupBy($fields)
  122. {
  123. if (is_array($fields)) {
  124. $this->group_by = $this->group_by + $fields;
  125. } else {
  126. $this->group_by[] = $fields;
  127. }
  128. return $this;
  129. }
  130. /**
  131. * @param $field string Field @ex 'field'
  132. * @param $order_desc bool Descendant sort direction
  133. * @return SqlCriteria
  134. * @desc Allow multiple calls
  135. */
  136. public function order($field, $order_desc = false)
  137. {
  138. $this->order['sort'][] = $field;
  139. if ($order_desc) {
  140. $this->order['order'][$field] = 'desc';
  141. }
  142. return $this;
  143. }
  144. /**
  145. * @param $offset int
  146. * @param $limit int
  147. * @return SqlCriteria
  148. */
  149. public function limit($offset = 0, $limit)
  150. {
  151. if ($offset) {
  152. $this->limit = (int) $offset . ',';
  153. }
  154. $this->limit .= (int) $limit;
  155. return $this;
  156. }
  157. /**
  158. * @param string|array $fields
  159. * @param bool $convert_to_db_expression
  160. * @ex SqlCriteria::select('field')
  161. * @ex SqlCriteria->select(array('field1', 'field2'))
  162. * @ex SqlCriteria->select('field1,field2')
  163. * @return SqlCriteria
  164. */
  165. public function select($fields, $convert_to_db_expression = false)
  166. {
  167. if (!is_array($fields)) {
  168. $fields = explode(',', $fields);
  169. }
  170. $fields = array_map(function($item){return trim($item);},$fields);
  171. if ($convert_to_db_expression) {
  172. $fields = array_map(function($item){return new DbExpr($item);},$fields);
  173. }
  174. $this->select = array_merge($this->select,$fields);
  175. return $this;
  176. }
  177. /**
  178. * @param $field string|bool If true then distinct by *
  179. * @return SqlCriteria
  180. */
  181. public function distinct($field)
  182. {
  183. $this->distinct = $field;
  184. return $this;
  185. }
  186. }