Refactoring. Fix errors. Add SqlModel.assoc*() methods.
This commit is contained in:
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
class SqlCriteria
|
class SqlCriteria
|
||||||
{
|
{
|
||||||
public $select = array('*');
|
public $select = '*';
|
||||||
|
|
||||||
public $distinct = '';
|
public $distinct = '';
|
||||||
|
|
||||||
@ -31,19 +31,15 @@ class SqlCriteria
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $fields array()
|
* @param $fields array @ex array('field1', 'field2' => SqlModel::ORDER_DESC)
|
||||||
* @param array $fields_to_desc
|
|
||||||
* @return SqlCriteria
|
* @return SqlCriteria
|
||||||
*/
|
*/
|
||||||
public function order($fields, $fields_to_desc = array())
|
public function order($fields)
|
||||||
{
|
{
|
||||||
if (!is_array($fields)) {
|
if (!is_array($fields)) {
|
||||||
$fields = array($fields);
|
$fields = array($fields);
|
||||||
}
|
}
|
||||||
foreach ($fields as $term) {
|
$this->order = $fields;
|
||||||
$term = $this->db->quoteIdentifier($term) . (in_array($term, $fields_to_desc) ? ' DESC' : '');
|
|
||||||
}
|
|
||||||
$this->order = implode(',', $fields);
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +66,7 @@ class SqlCriteria
|
|||||||
if (!is_array($select)) {
|
if (!is_array($select)) {
|
||||||
$select = array($select);
|
$select = array($select);
|
||||||
}
|
}
|
||||||
$this->select = implode(',', $select);
|
$this->select = $select;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,18 +19,23 @@ abstract class SqlModel extends Model
|
|||||||
const DISTINCT = 11;
|
const DISTINCT = 11;
|
||||||
const WHERE = 12;
|
const WHERE = 12;
|
||||||
const ORDER = 13;
|
const ORDER = 13;
|
||||||
const ORDER_TO_DESC = 14;
|
|
||||||
const LIMIT = 15;
|
const LIMIT = 15;
|
||||||
const OFFSET = 16;
|
const OFFSET = 16;
|
||||||
|
|
||||||
|
const ORDER_DESC = 20;
|
||||||
|
const ORDER_ASC = 21;
|
||||||
|
|
||||||
|
const ASSOC_BY_FIELD = 30;
|
||||||
|
const ASSOC_AS_ARRAY = 31;
|
||||||
|
const ASSOC_BY_FIELD_IN_ARRAY = 32;
|
||||||
|
|
||||||
protected static $criteria_data_keys = array(
|
protected static $criteria_data_keys = array(
|
||||||
self::SELECT,
|
self::SELECT,
|
||||||
self::DISTINCT,
|
self::DISTINCT,
|
||||||
self::WHERE,
|
self::WHERE,
|
||||||
self::ORDER,
|
self::ORDER,
|
||||||
/** self::ORDER_TO_DESC, // no to be process in foreach criteria_data @see SqlModel::find() */
|
|
||||||
self::LIMIT,
|
self::LIMIT,
|
||||||
/** self::OFFSET // no to be process in foreach criteria_data @see SqlModel::find() */
|
/** self::OFFSET // that key no to be a process in foreach criteria_data @see SqlModel::find() */
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -201,31 +206,60 @@ abstract class SqlModel extends Model
|
|||||||
*/
|
*/
|
||||||
protected function criteria($criteria)
|
protected function criteria($criteria)
|
||||||
{
|
{
|
||||||
|
if (!is_array($criteria->select)) {
|
||||||
|
$criteria->select = array(new DbExpr($criteria->select));
|
||||||
|
}
|
||||||
foreach ($criteria->select as $field => &$term) {
|
foreach ($criteria->select as $field => &$term) {
|
||||||
if (is_int($field)) {
|
if (is_int($field)) {
|
||||||
$term = $this->db->quoteIdentifier($term);
|
if ($term instanceof DbExpr) {
|
||||||
|
$term = (string) $term;
|
||||||
|
} else {
|
||||||
|
$term = $this->db->quoteIdentifier($term);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$term = $this->db->quoteIdentifier($field) . ' as ' . $this->db->quoteIdentifier($term);
|
$term = $this->db->quoteIdentifier($field) . ' as ' . $this->db->quoteIdentifier($term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ($criteria->where as $cond => &$term) {
|
foreach ($criteria->where as $cond => &$term) {
|
||||||
$term = $this->db->quoteInto($cond, $term);
|
if (is_int($cond)) {
|
||||||
|
if ($term instanceof DbExpr) {
|
||||||
|
$term = (string) $term;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (is_array($term)) {
|
||||||
|
$term = new DbExpr('(' . implode(',', array_map(function($item){return intval($item);}, $term)) . ')');
|
||||||
|
}
|
||||||
|
$term = $this->db->quoteInto($cond, $term);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
foreach ($criteria->order as $field => $term) {
|
foreach ($criteria->order as $field => $term) {
|
||||||
if (!is_int($field) && $term == 'desc') {
|
if (is_int($field)) {
|
||||||
$term = $term = $this->db->quoteIdentifier($field) . ' DESC';
|
|
||||||
} else {
|
|
||||||
$term = $this->db->quoteIdentifier($term);
|
$term = $this->db->quoteIdentifier($term);
|
||||||
|
} else {
|
||||||
|
$order_direction = '';
|
||||||
|
switch ($term) {
|
||||||
|
case self::ORDER_DESC:
|
||||||
|
$order_direction .= ' DESC';
|
||||||
|
break;
|
||||||
|
case self::ORDER_ASC:
|
||||||
|
$order_direction .= ' ASC';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$term = $this->db->quoteIdentifier($field) . $order_direction;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($criteria->distinct != '') {
|
if ($criteria->distinct != '') {
|
||||||
$criteria->distinct = 'DISTINCT ' . $this->db->quoteIdentifier($criteria->distinct);
|
$criteria->distinct = 'DISTINCT ' . $this->db->quoteIdentifier($criteria->distinct);
|
||||||
}
|
}
|
||||||
|
if ($criteria->limit != '') {
|
||||||
|
$criteria->limit = implode(',',array_map(function($item){return intval($item);},explode(',',$criteria->limit)));
|
||||||
|
}
|
||||||
return 'SELECT ' . (($criteria->distinct) ? $criteria->distinct : implode(',', $criteria->select))
|
return 'SELECT ' . (($criteria->distinct) ? $criteria->distinct : implode(',', $criteria->select))
|
||||||
. ' FROM ' . $this->db->quoteIdentifier($this->table)
|
. ' FROM ' . $this->table()
|
||||||
. (($criteria->where) ? (' WHERE ' . implode(' AND ', $criteria->where)) : '')
|
. (($criteria->where) ? (' WHERE ' . implode(' AND ', $criteria->where)) : '')
|
||||||
. (($criteria->order) ? (' ORDER BY ' . implode(',', $criteria->order)) : '')
|
. (($criteria->order) ? (' ORDER BY ' . implode(',', $criteria->order)) : '')
|
||||||
. (($criteria->limit) ? (' LIMIT ' . implode(',',array_map(function($item){return intval($item);},explode(',',$criteria->limit)))) : '');
|
. (($criteria->limit) ? (' LIMIT ' . $criteria->limit) : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -233,8 +267,7 @@ abstract class SqlModel extends Model
|
|||||||
* @ex array(
|
* @ex array(
|
||||||
* SqlModel::SELECT => '*',
|
* SqlModel::SELECT => '*',
|
||||||
* SqlModel::WHERE => array('field=?', 1),
|
* SqlModel::WHERE => array('field=?', 1),
|
||||||
* SqlModel::ORDER => array('last_name', 'first_name'),
|
* SqlModel::ORDER => array('last_name', 'first_name' => SqlModel::ORDER_DESC),
|
||||||
* SqlModel::ORDER_TO_DESC => array('last_name'),
|
|
||||||
* SqlModel::LIMIT => 10)
|
* SqlModel::LIMIT => 10)
|
||||||
* @return mixed|DbStatement[]
|
* @return mixed|DbStatement[]
|
||||||
*/
|
*/
|
||||||
@ -255,7 +288,7 @@ abstract class SqlModel extends Model
|
|||||||
$criteria->where($value);
|
$criteria->where($value);
|
||||||
break;
|
break;
|
||||||
case self::ORDER:
|
case self::ORDER:
|
||||||
$criteria->order($value, ((isset($criteria_data[self::ORDER_TO_DESC])) ? $criteria_data[self::ORDER_TO_DESC] : null));
|
$criteria->order($value);
|
||||||
break;
|
break;
|
||||||
case self::LIMIT:
|
case self::LIMIT:
|
||||||
$criteria->limit($value, ((isset($criteria_data[self::OFFSET])) ? $criteria_data[self::OFFSET] : null));
|
$criteria->limit($value, ((isset($criteria_data[self::OFFSET])) ? $criteria_data[self::OFFSET] : null));
|
||||||
@ -263,6 +296,82 @@ abstract class SqlModel extends Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self::fetchAll($this->criteria($criteria));
|
$data = $this->criteria($criteria);
|
||||||
|
if (isset($criteria_data[self::ASSOC_BY_FIELD])) {
|
||||||
|
return self::fetchAllAssocByField($data, array(), $criteria_data[self::ASSOC_BY_FIELD], ((isset($criteria_data[self::ASSOC_AS_ARRAY])) ? $criteria_data[self::ASSOC_AS_ARRAY] : false), ((isset($criteria_data[self::ASSOC_BY_FIELD_IN_ARRAY])) ? $criteria_data[self::ASSOC_BY_FIELD_IN_ARRAY] : null));
|
||||||
|
} else {
|
||||||
|
return self::fetchAll($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $data string
|
||||||
|
* @param $params array
|
||||||
|
* @param null|string $field
|
||||||
|
* @param bool $assoc_as_array
|
||||||
|
* @param null|string $field_assoc_in_array
|
||||||
|
* @return array
|
||||||
|
* @throws ErrorException|GeneralException
|
||||||
|
*/
|
||||||
|
protected function fetchAllAssocByField($data, $params, $field = null, $assoc_as_array = false, $field_assoc_in_array = null)
|
||||||
|
{
|
||||||
|
$items = self::fetchAll($data, $params);
|
||||||
|
if (is_null($field)) {
|
||||||
|
$field = $this->key;
|
||||||
|
}
|
||||||
|
return self::assocByField($items, $field, $assoc_as_array, $field_assoc_in_array);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $items
|
||||||
|
* @param $field
|
||||||
|
* @param bool $assoc_as_array
|
||||||
|
* @param $field_assoc_in_array null|string
|
||||||
|
* @param $disable_assoc_in_array bool
|
||||||
|
* @return array
|
||||||
|
* @throws ErrorException|GeneralException
|
||||||
|
*/
|
||||||
|
public function assocByField($items, $field, $assoc_as_array = false, $field_assoc_in_array = null, $disable_assoc_in_array = false)
|
||||||
|
{
|
||||||
|
$items_assoc_by_field = array();
|
||||||
|
$primary_key_not_exists_in_items = false;
|
||||||
|
foreach ($items as $item) {
|
||||||
|
if (!isset($item->{$field})) {
|
||||||
|
throw new GeneralException('Undefined field. ' . $field);
|
||||||
|
}
|
||||||
|
if ($assoc_as_array) {
|
||||||
|
if (!isset($items_assoc_by_field[$item->{$field}])) {
|
||||||
|
$items_assoc_by_field[$item->{$field}] = array();
|
||||||
|
}
|
||||||
|
$items_assoc_by_field[$item->{$field}][] = $item;
|
||||||
|
if (!$primary_key_not_exists_in_items && $this->key && !isset($item->{$this->key})) {
|
||||||
|
$primary_key_not_exists_in_items = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isset($items_assoc_by_field[$item->{$field}])) {
|
||||||
|
throw new ErrorException('Field not unique. May be use assoc_as_array. ' . $field);
|
||||||
|
}
|
||||||
|
$items_assoc_by_field[$item->{$field}] = $item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ассоциирование внутри каждого элемента массива по первичному ключу
|
||||||
|
// Если первичного ключа нет (не указан в модели или нет поля с первичным ключом в результах выборки) - ассоциирование внутри не производится
|
||||||
|
// Если указан $field_assoc_in_array - ассоциирование произовдится по этому полю (вернет ошибку, если этого поля нет в результатх выборки)
|
||||||
|
// Параметр $disable_assoc_in_array отключает ассоциирование внутри результирующего массива
|
||||||
|
if ($assoc_as_array && !$disable_assoc_in_array &&
|
||||||
|
(($this->key && !$primary_key_not_exists_in_items) || $field_assoc_in_array)
|
||||||
|
) {
|
||||||
|
foreach ($items_assoc_by_field as $key => $value) {
|
||||||
|
$items_assoc_by_field[$key] = self::assocByField($items_assoc_by_field[$key], (($field_assoc_in_array) ? $field_assoc_in_array : $this->key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $items_assoc_by_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function assocByFieldAndGetKeys($items, $field)
|
||||||
|
{
|
||||||
|
$items = self::assocByField($items, $field, true, null, true);
|
||||||
|
return array_keys($items);
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user