diff --git a/model/SqlCriteria.php b/model/SqlCriteria.php index 3c0649e..b5b9a4c 100644 --- a/model/SqlCriteria.php +++ b/model/SqlCriteria.php @@ -2,6 +2,20 @@ class SqlCriteria { + const JOIN_TYPE_DEFAULT = 100; + const JOIN_TYPE_LEFT = 101; + const JOIN_TYPE_RIGHT = 102; + const JOIN_TYPE_INNER = 103; + const JOIN_TYPE_OUTER = 104; + + private static $join_type_to_reserved_keyword = array( + self::JOIN_TYPE_DEFAULT => 'JOIN', + self::JOIN_TYPE_LEFT => 'LEFT JOIN', + self::JOIN_TYPE_RIGHT => 'RIGHT JOIN', + self::JOIN_TYPE_INNER => 'INNER JOIN', + self::JOIN_TYPE_OUTER => 'OUTER JOIN', + ); + private $select = array(); private $distinct = ''; @@ -23,6 +37,8 @@ class SqlCriteria private $sql_expression_params = array(); + private $sql_join_expressions = array(); + /** * @param $model SqlModel * @param $sql_expression string|null Sql expression with SELECT and FROM operators. If fetched, then SqlCriteria::select(), SqlCriteria::distinct() disabled for use. @@ -40,14 +56,39 @@ class SqlCriteria */ public function find() { + // preparing link expressions (if exists) + if ($this->sql_join_expressions) { + if (!$this->sql_expression) { + $select = $this->model->getDb()->selectExpr($this->select, $this->distinct); + $this->sql_expression = 'SELECT ' . $select . ' FROM :table'; + } + $this->sql_expression .= ' ' . implode(' ', $this->sql_join_expressions); + } 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); } + public function delete() + { + return $this->model->find('', '', $this->where, null, null, null, null, 'DELETE FROM :table', $this->sql_expression_params)->affectedRows(); + } + public function count() { return $this->model->find(new DbExpr('COUNT(*) as count'), '', $this->where, null, null, null, null, $this->sql_expression, $this->sql_expression_params)->fetchField('count'); } + public function join($join_table_name, $join_field_name, $donor_table_name = null, $donor_field_name = null, $join_type = self::JOIN_TYPE_DEFAULT) + { + $donor_field_name = $donor_field_name ? : $join_field_name; + $donor_table_name = $donor_table_name ? : 'table'; + $this->sql_join_expressions[] = self::$join_type_to_reserved_keyword[$join_type] + . ' :' . $join_table_name + . ' ON :' . $donor_table_name . '.' . $donor_field_name . '=' + . ':' . $join_table_name . '.' . $join_field_name; + $this->sql_expression_params[$join_table_name] = new DbExpr($this->model->identify($join_table_name)); + return $this; + } + /** * @param $cond string|array Condition with "?" placeholder @ex 'field=?' or 'field=1' or array('field=?' => 1', 'field=1') * @param $value string|array|DbExpr|null Value. Array transformed to DbExpr(implode(',' Array)) All elements in the array mast be integer @@ -140,17 +181,21 @@ class SqlCriteria /** * @param string|array $fields + * @param bool $convert_to_db_expression * @ex SqlCriteria::select('field') * @ex SqlCriteria->select(array('field1', 'field2')) * @ex SqlCriteria->select('field1,field2') * @return SqlCriteria */ - public function select($fields) + public function select($fields, $convert_to_db_expression = false) { if (!is_array($fields)) { $fields = explode(',', $fields); } $fields = array_map(function($item){return trim($item);},$fields); + if ($convert_to_db_expression) { + $fields = array_map(function($item){return new DbExpr($item);},$fields); + } $this->select = array_merge($this->select,$fields); return $this; } diff --git a/model/SqlModel.php b/model/SqlModel.php index 7b5154a..181c4ab 100644 --- a/model/SqlModel.php +++ b/model/SqlModel.php @@ -33,6 +33,11 @@ abstract class SqlModel extends Model return $this->db->quote($value); } + public function getDb() + { + return $this->db; + } + /** * @param int $id * @return object @@ -209,7 +214,7 @@ abstract class SqlModel extends Model $group_by = $this->db->groupByExpr($group_by); $order = isset($order['sort']) ? $this->order($order, $order['sort']) : false; $limit = $this->db->limitExpr($limit); - $result_items = $this->fetchAll( + $result = $this->query( (($sql_expression) ? $sql_expression : ('SELECT ' . $select . ' FROM ' . $this->table())) . (($where) ? (' WHERE ' . $where) : '') . (($group_by) ? (' GROUP BY ' . $group_by) : '') @@ -218,7 +223,7 @@ abstract class SqlModel extends Model $sql_expression_params, $cache_key ); - return new SqlResultProvider($result_items); + return new SqlResultProvider($result); } /** diff --git a/model/SqlResultCollection.php b/model/SqlResultCollection.php new file mode 100644 index 0000000..0d8a74d --- /dev/null +++ b/model/SqlResultCollection.php @@ -0,0 +1,19 @@ +items = $items; + foreach ($items as $item) { + parent::append($item); + } + } + + public function fetchAll() + { + return $this->items; + } +} \ No newline at end of file diff --git a/model/SqlResultProvider.php b/model/SqlResultProvider.php index 0bae36f..cae4e77 100644 --- a/model/SqlResultProvider.php +++ b/model/SqlResultProvider.php @@ -5,23 +5,44 @@ class SqlResultProvider /** * @var array */ + private $result; + + /** + * @var array + * @desc my be changed in assoc method + */ private $result_items; + /** + * @var array + */ private $result_items_base; /** - * @param $result_items array + * @param $result DbStatement */ - public function __construct($result_items) + public function __construct($result) { - $this->result_items = $result_items; + $this->result = $result; } - public function assoc($field, $assoc_as_array = false) + private function defineResultItems() { if (is_null($this->result_items_base)) { - $this->result_items_base = $this->result_items; + $this->result_items_base = $this->result->fetchAll(); + $this->result_items = $this->result_items_base; } + } + + /** + * @param $field string + * @param bool $assoc_as_array + * @return $this SqlResultProvider + * @throws ErrorException + */ + public function assoc($field, $assoc_as_array = false) + { + $this->defineResultItems(); $result_items_assoc = array(); foreach ($this->result_items_base as $item) { if (!isset($item->{$field})) { @@ -42,7 +63,7 @@ class SqlResultProvider // Ассоциирование внутри каждого элемента массива if ($assoc_as_array) { foreach ($result_items_assoc as &$value) { - $value = new SqlResultProvider($value); + $value = new SqlResultCollection($value); } } $this->result_items = $result_items_assoc; @@ -51,18 +72,22 @@ class SqlResultProvider public function getKeys() { - return array_keys($this->result_items); + return array_keys($this->result); } + /** + * @return DbStatement[]|SqlResultCollection[] + */ public function fetchAll() { + $this->defineResultItems(); return $this->result_items; } /** * @param $key * @return mixed - * TODO: метод актуален только после вызова assoc + * метод актуален после вызова assoc */ public function fetchKey($key) { @@ -72,19 +97,19 @@ class SqlResultProvider /** * @param $field * @return mixed - * TODO: метод не актуален после вызова assoc с параметров assoc_as_array = true */ public function fetchField($field) { - $item = current($this->result_items); - if ($item) { - return $item->{$field}; - } - return false; + return $this->result->fetchField($field); + } + + public function fetch($style = Db::FETCH_OBJ) + { + return $this->result->fetch($style); } - public function fetch() + public function affectedRows() { - return current($this->result_items); + return $this->result->affectedRows(); } } \ No newline at end of file