Commit 65338972 authored by Carsten Brandt's avatar Carsten Brandt

refactored ActiveRecord classes to use Interfaces and traits

this allows us to implement other activerecord implementations based on
NoSQL dbms
parent c8c7f59d
...@@ -167,8 +167,8 @@ For ordering results `orderBy` and `addOrderBy` could be used: ...@@ -167,8 +167,8 @@ For ordering results `orderBy` and `addOrderBy` could be used:
```php ```php
$query->orderBy([ $query->orderBy([
'id' => Query::SORT_ASC, 'id' => SORT_ASC,
'name' => Query::SORT_DESC, 'name' => SORT_DESC,
]); ]);
``` ```
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\ar;
use yii\db\QueryInterface;
/**
* ActiveQueryInterface defines the common interface to be implemented by active record relation classes.
*
* A class implementing this interface should also use [[ActiveQueryTrait]].
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
interface ActiveQueryInterface extends QueryInterface
{
/**
* Sets the [[asArray]] property.
* @param boolean $value whether to return the query results in terms of arrays instead of Active Records.
* @return static the query object itself
*/
public function asArray($value = true);
/**
* Specifies the relations with which this query should be performed.
*
* The parameters to this method can be either one or multiple strings, or a single array
* of relation names and the optional callbacks to customize the relations.
*
* A relation name can refer to a relation defined in [[modelClass]]
* or a sub-relation that stands for a relation of a related record.
* For example, `orders.address` means the `address` relation defined
* in the model class corresponding to the `orders` relation.
*
* The followings are some usage examples:
*
* ~~~
* // find customers together with their orders and country
* Customer::find()->with('orders', 'country')->all();
* // find customers together with their orders and the orders' shipping address
* Customer::find()->with('orders.address')->all();
* // find customers together with their country and orders of status 1
* Customer::find()->with([
* 'orders' => function($query) {
* $query->andWhere('status = 1');
* },
* 'country',
* ])->all();
* ~~~
*
* @return static the query object itself
*/
public function with();
}
...@@ -10,10 +10,7 @@ namespace yii\ar; ...@@ -10,10 +10,7 @@ namespace yii\ar;
use yii\db\ActiveRecord; use yii\db\ActiveRecord;
/** /**
* ActiveQuery represents a DB query associated with an Active Record class. * ActiveQueryTrait implements the common set of methods that are used by DB queries associated with an Active Record class.
*
* ActiveQuery instances are usually created by [[ActiveRecord::find()]], [[ActiveRecord::findBySql()]]
* and [[ActiveRecord::count()]].
* *
* ActiveQuery mainly provides the following methods to retrieve the query results: * ActiveQuery mainly provides the following methods to retrieve the query results:
* *
...@@ -150,6 +147,11 @@ trait ActiveQueryTrait ...@@ -150,6 +147,11 @@ trait ActiveQueryTrait
return parent::indexBy($column); return parent::indexBy($column);
} }
/**
* Converts found rows into model instances
* @param array $rows
* @return array|ActiveRecord[]
*/
private function createModels($rows) private function createModels($rows)
{ {
$models = []; $models = [];
...@@ -187,6 +189,10 @@ trait ActiveQueryTrait ...@@ -187,6 +189,10 @@ trait ActiveQueryTrait
return $models; return $models;
} }
/**
* @param ActiveRecord[] $models
* @param array $with
*/
private function populateRelations(&$models, $with) private function populateRelations(&$models, $with)
{ {
$primaryModel = new $this->modelClass; $primaryModel = new $this->modelClass;
...@@ -203,7 +209,7 @@ trait ActiveQueryTrait ...@@ -203,7 +209,7 @@ trait ActiveQueryTrait
/** /**
* @param ActiveRecord $model * @param ActiveRecord $model
* @param array $with * @param array $with
* @return ActiveRelation[] * @return ActiveRelationInterface[]
*/ */
private function normalizeRelations($model, $with) private function normalizeRelations($model, $with)
{ {
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\ar;
/**
* ActiveRelationInterface defines the common interface to be implemented by active record relation classes.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
interface ActiveRelationInterface extends ActiveQueryInterface
{
/**
* Specifies the relation associated with the pivot table.
* @param string $relationName the relation name. This refers to a relation declared in [[primaryModel]].
* @param callable $callable a PHP callback for customizing the relation associated with the pivot table.
* Its signature should be `function($query)`, where `$query` is the query to be customized.
* @return static the relation object itself.
*/
public function via($relationName, $callable = null);
/**
* Finds the related records and populates them into the primary models.
* This method is internally used by [[ActiveQuery]]. Do not call it directly.
* @param string $name the relation name
* @param array $primaryModels primary models
* @return array the related models
*/
public function findWith($name, &$primaryModels);
}
...@@ -23,6 +23,7 @@ use yii\db\ActiveRecord; ...@@ -23,6 +23,7 @@ use yii\db\ActiveRecord;
* If a relation involves a pivot table, it may be specified by [[via()]] or [[viaTable()]] method. * If a relation involves a pivot table, it may be specified by [[via()]] or [[viaTable()]] method.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0 * @since 2.0
*/ */
trait ActiveRelationTrait trait ActiveRelationTrait
......
...@@ -8,11 +8,11 @@ ...@@ -8,11 +8,11 @@
namespace yii\data; namespace yii\data;
use Yii; use Yii;
use yii\ar\ActiveQueryInterface;
use yii\base\InvalidConfigException; use yii\base\InvalidConfigException;
use yii\base\Model; use yii\base\Model;
use yii\db\Query;
use yii\db\ActiveQuery;
use yii\db\Connection; use yii\db\Connection;
use yii\db\QueryInterface;
/** /**
* ActiveDataProvider implements a data provider based on [[Query]] and [[ActiveQuery]]. * ActiveDataProvider implements a data provider based on [[Query]] and [[ActiveQuery]].
...@@ -54,7 +54,7 @@ use yii\db\Connection; ...@@ -54,7 +54,7 @@ use yii\db\Connection;
class ActiveDataProvider extends BaseDataProvider class ActiveDataProvider extends BaseDataProvider
{ {
/** /**
* @var Query the query that is used to fetch data models and [[totalCount]] * @var QueryInterface the query that is used to fetch data models and [[totalCount]]
* if it is not explicitly set. * if it is not explicitly set.
*/ */
public $query; public $query;
...@@ -97,8 +97,8 @@ class ActiveDataProvider extends BaseDataProvider ...@@ -97,8 +97,8 @@ class ActiveDataProvider extends BaseDataProvider
*/ */
protected function prepareModels() protected function prepareModels()
{ {
if (!$this->query instanceof Query) { if (!$this->query instanceof QueryInterface) {
throw new InvalidConfigException('The "query" property must be an instance of Query or its subclass.'); throw new InvalidConfigException('The "query" property must be an instance of a class that implements the QueryInterface e.g. yii\db\Query or its subclasses.');
} }
if (($pagination = $this->getPagination()) !== false) { if (($pagination = $this->getPagination()) !== false) {
$pagination->totalCount = $this->getTotalCount(); $pagination->totalCount = $this->getTotalCount();
...@@ -125,7 +125,7 @@ class ActiveDataProvider extends BaseDataProvider ...@@ -125,7 +125,7 @@ class ActiveDataProvider extends BaseDataProvider
} }
} }
return $keys; return $keys;
} elseif ($this->query instanceof ActiveQuery) { } elseif ($this->query instanceof ActiveQueryInterface) {
/** @var \yii\db\ActiveRecord $class */ /** @var \yii\db\ActiveRecord $class */
$class = $this->query->modelClass; $class = $this->query->modelClass;
$pks = $class::primaryKey(); $pks = $class::primaryKey();
...@@ -154,11 +154,11 @@ class ActiveDataProvider extends BaseDataProvider ...@@ -154,11 +154,11 @@ class ActiveDataProvider extends BaseDataProvider
*/ */
protected function prepareTotalCount() protected function prepareTotalCount()
{ {
if (!$this->query instanceof Query) { if (!$this->query instanceof QueryInterface) {
throw new InvalidConfigException('The "query" property must be an instance of Query or its subclass.'); throw new InvalidConfigException('The "query" property must be an instance of a class that implements the QueryInterface e.g. yii\db\Query or its subclasses.');
} }
$query = clone $this->query; $query = clone $this->query;
return (int) $query->limit(-1)->offset(-1)->count('*', $this->db); return (int) $query->limit(-1)->offset(-1)->count($this->db);
} }
/** /**
...@@ -167,7 +167,7 @@ class ActiveDataProvider extends BaseDataProvider ...@@ -167,7 +167,7 @@ class ActiveDataProvider extends BaseDataProvider
public function setSort($value) public function setSort($value)
{ {
parent::setSort($value); parent::setSort($value);
if (($sort = $this->getSort()) !== false && empty($sort->attributes) && $this->query instanceof ActiveQuery) { if (($sort = $this->getSort()) !== false && empty($sort->attributes) && $this->query instanceof ActiveQueryInterface) {
/** @var Model $model */ /** @var Model $model */
$model = new $this->query->modelClass; $model = new $this->query->modelClass;
foreach ($model->attributes() as $attribute) { foreach ($model->attributes() as $attribute) {
......
...@@ -7,12 +7,13 @@ ...@@ -7,12 +7,13 @@
*/ */
namespace yii\db; namespace yii\db;
use yii\ar\ActiveQueryInterface;
use yii\ar\ActiveQueryTrait;
/** /**
* ActiveQuery represents a DB query associated with an Active Record class. * ActiveQuery represents a DB query associated with an Active Record class.
* *
* ActiveQuery instances are usually created by [[ActiveRecord::find()]], [[ActiveRecord::findBySql()]] * ActiveQuery instances are usually created by [[ActiveRecord::find()]] and [[ActiveRecord::findBySql()]].
* and [[ActiveRecord::count()]].
* *
* ActiveQuery mainly provides the following methods to retrieve the query results: * ActiveQuery mainly provides the following methods to retrieve the query results:
* *
...@@ -42,11 +43,12 @@ namespace yii\db; ...@@ -42,11 +43,12 @@ namespace yii\db;
* ~~~ * ~~~
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0 * @since 2.0
*/ */
class ActiveQuery extends Query class ActiveQuery extends Query implements ActiveQueryInterface
{ {
use \yii\ar\ActiveQueryTrait; use ActiveQueryTrait;
/** /**
* @var string the SQL statement to be executed for retrieving AR records. * @var string the SQL statement to be executed for retrieving AR records.
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
namespace yii\db; namespace yii\db;
use yii\ar\ActiveRelationInterface;
use yii\base\InvalidConfigException; use yii\base\InvalidConfigException;
use yii\base\Model; use yii\base\Model;
use yii\base\InvalidParamException; use yii\base\InvalidParamException;
...@@ -36,6 +37,7 @@ use yii\helpers\Inflector; ...@@ -36,6 +37,7 @@ use yii\helpers\Inflector;
* the key value is null). This property is read-only. * the key value is null). This property is read-only.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0 * @since 2.0
*/ */
class ActiveRecord extends Model class ActiveRecord extends Model
...@@ -94,10 +96,6 @@ class ActiveRecord extends Model ...@@ -94,10 +96,6 @@ class ActiveRecord extends Model
*/ */
const OP_ALL = 0x07; const OP_ALL = 0x07;
/**
* @var string the name of the class to use for relations.
*/
protected $relationClassName = 'yii\\db\\ActiveRelation';
/** /**
* @var array attribute values indexed by attribute names * @var array attribute values indexed by attribute names
*/ */
...@@ -256,7 +254,7 @@ class ActiveRecord extends Model ...@@ -256,7 +254,7 @@ class ActiveRecord extends Model
/** /**
* Creates an [[ActiveQuery]] instance. * Creates an [[ActiveQuery]] instance.
* This method is called by [[find()]], [[findBySql()]] and [[count()]] to start a SELECT query. * This method is called by [[find()]], [[findBySql()]] to start a SELECT query.
* You may override this method to return a customized query (e.g. `CustomerQuery` specified * You may override this method to return a customized query (e.g. `CustomerQuery` specified
* written for querying `Customer` purpose.) * written for querying `Customer` purpose.)
* @return ActiveQuery the newly created [[ActiveQuery]] instance. * @return ActiveQuery the newly created [[ActiveQuery]] instance.
...@@ -389,7 +387,7 @@ class ActiveRecord extends Model ...@@ -389,7 +387,7 @@ class ActiveRecord extends Model
return $this->_related[$name]; return $this->_related[$name];
} }
$value = parent::__get($name); $value = parent::__get($name);
if ($value instanceof $this->relationClassName) { if ($value instanceof ActiveRelationInterface) {
return $this->_related[$name] = $value->multiple ? $value->all() : $value->one(); return $this->_related[$name] = $value->multiple ? $value->all() : $value->one();
} else { } else {
return $value; return $value;
...@@ -478,7 +476,7 @@ class ActiveRecord extends Model ...@@ -478,7 +476,7 @@ class ActiveRecord extends Model
*/ */
public function hasOne($class, $link) public function hasOne($class, $link)
{ {
return new $this->relationClassName([ return $this->createActiveRelation([
'modelClass' => $class, 'modelClass' => $class,
'primaryModel' => $this, 'primaryModel' => $this,
'link' => $link, 'link' => $link,
...@@ -516,7 +514,7 @@ class ActiveRecord extends Model ...@@ -516,7 +514,7 @@ class ActiveRecord extends Model
*/ */
public function hasMany($class, $link) public function hasMany($class, $link)
{ {
return new $this->relationClassName([ return $this->createActiveRelation([
'modelClass' => $class, 'modelClass' => $class,
'primaryModel' => $this, 'primaryModel' => $this,
'link' => $link, 'link' => $link,
...@@ -524,6 +522,18 @@ class ActiveRecord extends Model ...@@ -524,6 +522,18 @@ class ActiveRecord extends Model
]); ]);
} }
/**
* Creates an [[ActiveRelation]] instance.
* This method is called by [[hasOne()]] and [[hasMany()]] to create a relation instance.
* You may override this method to return a customized relation.
* @param array $config the configuration passed to the ActiveRelation class.
* @return ActiveRelation the newly created [[ActiveRelation]] instance.
*/
protected function createActiveRelation($config = [])
{
return new ActiveRelation($config);
}
/** /**
* Populates the named relation with the related records. * Populates the named relation with the related records.
* Note that this method does not check if the relation exists or not. * Note that this method does not check if the relation exists or not.
...@@ -1287,7 +1297,7 @@ class ActiveRecord extends Model ...@@ -1287,7 +1297,7 @@ class ActiveRecord extends Model
$getter = 'get' . $name; $getter = 'get' . $name;
try { try {
$relation = $this->$getter(); $relation = $this->$getter();
if ($relation instanceof $this->relationClassName) { if ($relation instanceof ActiveRelationInterface) {
return $relation; return $relation;
} else { } else {
return null; return null;
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
*/ */
namespace yii\db; namespace yii\db;
use yii\ar\ActiveRelationInterface;
use yii\ar\ActiveRelationTrait;
/** /**
* ActiveRelation represents a relation between two Active Record classes. * ActiveRelation represents a relation between two Active Record classes.
...@@ -24,17 +26,12 @@ namespace yii\db; ...@@ -24,17 +26,12 @@ namespace yii\db;
* or [[viaTable()]] to set this property instead of directly setting it. * or [[viaTable()]] to set this property instead of directly setting it.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0 * @since 2.0
*/ */
class ActiveRelation extends ActiveQuery class ActiveRelation extends ActiveQuery implements ActiveRelationInterface
{ {
use \yii\ar\ActiveRelationTrait; use ActiveRelationTrait;
/**
* @var array|ActiveRelation the query associated with the pivot table. Please call [[via()]]
* or [[viaTable()]] to set this property instead of directly setting it.
*/
public $via;
/** /**
* Specifies the pivot table. * Specifies the pivot table.
......
...@@ -33,23 +33,13 @@ use yii\base\Component; ...@@ -33,23 +33,13 @@ use yii\base\Component;
* ~~~ * ~~~
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0 * @since 2.0
*/ */
class Query extends Component class Query extends Component implements QueryInterface
{ {
use QueryTrait; use QueryTrait;
/**
* Sort ascending
* @see orderBy()
*/
const SORT_ASC = false;
/**
* Sort descending
* @see orderBy()
*/
const SORT_DESC = true;
/** /**
* @var array the columns being selected. For example, `['id', 'name']`. * @var array the columns being selected. For example, `['id', 'name']`.
* This is used to construct the SELECT clause in a SQL statement. If not set, if means selecting all columns. * This is used to construct the SELECT clause in a SQL statement. If not set, if means selecting all columns.
...@@ -189,13 +179,13 @@ class Query extends Component ...@@ -189,13 +179,13 @@ class Query extends Component
/** /**
* Returns the number of records. * Returns the number of records.
* @param Connection $db the database connection used to generate the SQL statement.
* If this parameter is not given (or null), the `db` application component will be used.
* @param string $q the COUNT expression. Defaults to '*'. * @param string $q the COUNT expression. Defaults to '*'.
* Make sure you properly quote column names in the expression. * Make sure you properly quote column names in the expression.
* @param Connection $db the database connection used to generate the SQL statement.
* If this parameter is not given, the `db` application component will be used.
* @return integer number of records * @return integer number of records
*/ */
public function count($q = '*', $db = null) public function count($db = null, $q = '*')
{ {
$this->select = ["COUNT($q)"]; $this->select = ["COUNT($q)"];
return $this->createCommand($db)->queryScalar(); return $this->createCommand($db)->queryScalar();
......
...@@ -683,7 +683,7 @@ class QueryBuilder extends \yii\base\Object ...@@ -683,7 +683,7 @@ class QueryBuilder extends \yii\base\Object
if (is_object($direction)) { if (is_object($direction)) {
$orders[] = (string)$direction; $orders[] = (string)$direction;
} else { } else {
$orders[] = $this->db->quoteColumnName($name) . ($direction === Query::SORT_DESC ? ' DESC' : ''); $orders[] = $this->db->quoteColumnName($name) . ($direction === SORT_DESC ? ' DESC' : '');
} }
} }
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\db;
/**
* The QueryInterface defines the minimum set of methods to be implemented by a database query.
*
* The default implementation of this interface is provided by [[QueryTrait]].
*
* It has support for getting [[one]] instance or [[all]].
* Allows pagination via [[limit]] and [[offset]].
* Sorting is supported via [[orderBy]] and items can be limited to match some conditions using [[where]].
*
* By calling [[createCommand()]], we can get a [[Command]] instance which can be further
* used to perform/execute the DB query against a database.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
interface QueryInterface
{
/**
* Executes the query and returns all results as an array.
* @param Connection $db the database connection used to execute the query.
* If this parameter is not given, the `db` application component will be used.
* @return array the query results. If the query results in nothing, an empty array will be returned.
*/
public function all($db = null);
/**
* Executes the query and returns a single row of result.
* @param Connection $db the database connection used to execute the query.
* If this parameter is not given, the `db` application component will be used.
* @return array|boolean the first row (in terms of an array) of the query result. False is returned if the query
* results in nothing.
*/
public function one($db = null);
/**
* Returns the number of records.
* @param Connection $db the database connection used to execute the query.
* If this parameter is not given, the `db` application component will be used.
* @return integer number of records
*/
public function count($db = null);
/**
* Returns a value indicating whether the query result contains any row of data.
* @param Connection $db the database connection used to execute the query.
* If this parameter is not given, the `db` application component will be used.
* @return boolean whether the query result contains any row of data.
*/
public function exists($db = null);
/**
* Sets the [[indexBy]] property.
* @param string|callable $column the name of the column by which the query results should be indexed by.
* This can also be a callable (e.g. anonymous function) that returns the index value based on the given
* row data. The signature of the callable should be:
*
* ~~~
* function ($row)
* {
* // return the index value corresponding to $row
* }
* ~~~
*
* @return static the query object itself
*/
public function indexBy($column);
/**
* Sets the WHERE part of the query.
*
* The method requires a $condition parameter.
*
* The $condition parameter should be an array in one of the following two formats:
*
* - hash format: `['column1' => value1, 'column2' => value2, ...]`
* - operator format: `[operator, operand1, operand2, ...]`
*
* A condition in hash format represents the following SQL expression in general:
* `column1=value1 AND column2=value2 AND ...`. In case when a value is an array,
* an `IN` expression will be generated. And if a value is null, `IS NULL` will be used
* in the generated expression. Below are some examples:
*
* - `['type' => 1, 'status' => 2]` generates `(type = 1) AND (status = 2)`.
* - `['id' => [1, 2, 3], 'status' => 2]` generates `(id IN (1, 2, 3)) AND (status = 2)`.
* - `['status' => null] generates `status IS NULL`.
*
* A condition in operator format generates the SQL expression according to the specified operator, which
* can be one of the followings:
*
* - `and`: the operands should be concatenated together using `AND`. For example,
* `['and', 'id=1', 'id=2']` will generate `id=1 AND id=2`. If an operand is an array,
* it will be converted into a string using the rules described here. For example,
* `['and', 'type=1', ['or', 'id=1', 'id=2']]` will generate `type=1 AND (id=1 OR id=2)`.
* The method will NOT do any quoting or escaping.
*
* - `or`: similar to the `and` operator except that the operands are concatenated using `OR`.
*
* - `between`: operand 1 should be the column name, and operand 2 and 3 should be the
* starting and ending values of the range that the column is in.
* For example, `['between', 'id', 1, 10]` will generate `id BETWEEN 1 AND 10`.
*
* - `not between`: similar to `between` except the `BETWEEN` is replaced with `NOT BETWEEN`
* in the generated condition.
*
* - `in`: operand 1 should be a column or DB expression, and operand 2 be an array representing
* the range of the values that the column or DB expression should be in. For example,
* `['in', 'id', [1, 2, 3]]` will generate `id IN (1, 2, 3)`.
* The method will properly quote the column name and escape values in the range.
*
* - `not in`: similar to the `in` operator except that `IN` is replaced with `NOT IN` in the generated condition.
*
* - `like`: operand 1 should be a column or DB expression, and operand 2 be a string or an array representing
* the values that the column or DB expression should be like.
* For example, `['like', 'name', '%tester%']` will generate `name LIKE '%tester%'`.
* When the value range is given as an array, multiple `LIKE` predicates will be generated and concatenated
* using `AND`. For example, `['like', 'name', ['%test%', '%sample%']]` will generate
* `name LIKE '%test%' AND name LIKE '%sample%'`.
* The method will properly quote the column name and escape values in the range.
*
* - `or like`: similar to the `like` operator except that `OR` is used to concatenate the `LIKE`
* predicates when operand 2 is an array.
*
* - `not like`: similar to the `like` operator except that `LIKE` is replaced with `NOT LIKE`
* in the generated condition.
*
* - `or not like`: similar to the `not like` operator except that `OR` is used to concatenate
* the `NOT LIKE` predicates.
*
* @param array $condition the conditions that should be put in the WHERE part.
* @return static the query object itself
* @see andWhere()
* @see orWhere()
*/
public function where($condition);
/**
* Adds an additional WHERE condition to the existing one.
* The new condition and the existing one will be joined using the 'AND' operator.
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @return static the query object itself
* @see where()
* @see orWhere()
*/
public function andWhere($condition);
/**
* Adds an additional WHERE condition to the existing one.
* The new condition and the existing one will be joined using the 'OR' operator.
* @param string|array $condition the new WHERE condition. Please refer to [[where()]]
* on how to specify this parameter.
* @return static the query object itself
* @see where()
* @see andWhere()
*/
public function orWhere($condition);
/**
* Sets the ORDER BY part of the query.
* @param string|array $columns the columns (and the directions) to be ordered by.
* Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array
* (e.g. `['id' => SORT_ASC, 'name' => SORT_DESC]`).
* The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression).
* @return static the query object itself
* @see addOrderBy()
*/
public function orderBy($columns);
/**
* Adds additional ORDER BY columns to the query.
* @param string|array $columns the columns (and the directions) to be ordered by.
* Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array
* (e.g. `['id' => SORT_ASC, 'name' => SORT_DESC]`).
* The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression).
* @return static the query object itself
* @see orderBy()
*/
public function addOrderBy($columns);
/**
* Sets the LIMIT part of the query.
* @param integer $limit the limit. Use null or negative value to disable limit.
* @return static the query object itself
*/
public function limit($limit);
/**
* Sets the OFFSET part of the query.
* @param integer $offset the offset. Use null or negative value to disable offset.
* @return static the query object itself
*/
public function offset($offset);
}
\ No newline at end of file
...@@ -7,18 +7,6 @@ ...@@ -7,18 +7,6 @@
namespace yii\db; namespace yii\db;
// TODO where to put these constants?
/**
* Sort ascending
* @see orderBy
*/
const SORT_ASC = false;
/**
* Sort descending
* @see orderBy
*/
const SORT_DESC = true;
/** /**
* The BaseQuery trait represents the minimum method set of a database Query. * The BaseQuery trait represents the minimum method set of a database Query.
* *
...@@ -53,8 +41,10 @@ trait QueryTrait ...@@ -53,8 +41,10 @@ trait QueryTrait
/** /**
* @var array how to sort the query results. This is used to construct the ORDER BY clause in a SQL statement. * @var array how to sort the query results. This is used to construct the ORDER BY clause in a SQL statement.
* The array keys are the columns to be sorted by, and the array values are the corresponding sort directions which * The array keys are the columns to be sorted by, and the array values are the corresponding sort directions which
* can be either [[Query::SORT_ASC]] or [[Query::SORT_DESC]]. The array may also contain [[Expression]] objects. * can be either [SORT_ASC](http://php.net/manual/en/array.constants.php#constant.sort-asc)
* If that is the case, the expressions will be converted into strings without any change. * or [SORT_DESC](http://php.net/manual/en/array.constants.php#constant.sort-desc).
* The array may also contain [[Expression]] objects. If that is the case, the expressions
* will be converted into strings without any change.
*/ */
public $orderBy; public $orderBy;
/** /**
...@@ -85,91 +75,10 @@ trait QueryTrait ...@@ -85,91 +75,10 @@ trait QueryTrait
return $this; return $this;
} }
/**
* Executes the query and returns all results as an array.
* @return array the query results. If the query results in nothing, an empty array will be returned.
*/
abstract public function all();
/**
* Executes the query and returns a single row of result.
* @return array|boolean the first row (in terms of an array) of the query result. False is returned if the query
* results in nothing.
*/
abstract public function one();
/**
* Returns the number of records.
* @return integer number of records
*/
abstract public function count();
/**
* Returns a value indicating whether the query result contains any row of data.
* @return boolean whether the query result contains any row of data.
*/
abstract public function exists();
/** /**
* Sets the WHERE part of the query. * Sets the WHERE part of the query.
* *
* The method requires a $condition parameter. * See [[QueryInterface::where()]] for detailed documentation.
*
* The $condition parameter should be an array in one of the following two formats:
*
* - hash format: `['column1' => value1, 'column2' => value2, ...]`
* - operator format: `[operator, operand1, operand2, ...]`
*
* A condition in hash format represents the following SQL expression in general:
* `column1=value1 AND column2=value2 AND ...`. In case when a value is an array,
* an `IN` expression will be generated. And if a value is null, `IS NULL` will be used
* in the generated expression. Below are some examples:
*
* - `['type' => 1, 'status' => 2]` generates `(type = 1) AND (status = 2)`.
* - `['id' => [1, 2, 3], 'status' => 2]` generates `(id IN (1, 2, 3)) AND (status = 2)`.
* - `['status' => null] generates `status IS NULL`.
*
* A condition in operator format generates the SQL expression according to the specified operator, which
* can be one of the followings:
*
* - `and`: the operands should be concatenated together using `AND`. For example,
* `['and', 'id=1', 'id=2']` will generate `id=1 AND id=2`. If an operand is an array,
* it will be converted into a string using the rules described here. For example,
* `['and', 'type=1', ['or', 'id=1', 'id=2']]` will generate `type=1 AND (id=1 OR id=2)`.
* The method will NOT do any quoting or escaping.
*
* - `or`: similar to the `and` operator except that the operands are concatenated using `OR`.
*
* - `between`: operand 1 should be the column name, and operand 2 and 3 should be the
* starting and ending values of the range that the column is in.
* For example, `['between', 'id', 1, 10]` will generate `id BETWEEN 1 AND 10`.
*
* - `not between`: similar to `between` except the `BETWEEN` is replaced with `NOT BETWEEN`
* in the generated condition.
*
* - `in`: operand 1 should be a column or DB expression, and operand 2 be an array representing
* the range of the values that the column or DB expression should be in. For example,
* `['in', 'id', [1, 2, 3]]` will generate `id IN (1, 2, 3)`.
* The method will properly quote the column name and escape values in the range.
*
* - `not in`: similar to the `in` operator except that `IN` is replaced with `NOT IN` in the generated condition.
*
* - `like`: operand 1 should be a column or DB expression, and operand 2 be a string or an array representing
* the values that the column or DB expression should be like.
* For example, `['like', 'name', '%tester%']` will generate `name LIKE '%tester%'`.
* When the value range is given as an array, multiple `LIKE` predicates will be generated and concatenated
* using `AND`. For example, `['like', 'name', ['%test%', '%sample%']]` will generate
* `name LIKE '%test%' AND name LIKE '%sample%'`.
* The method will properly quote the column name and escape values in the range.
*
* - `or like`: similar to the `like` operator except that `OR` is used to concatenate the `LIKE`
* predicates when operand 2 is an array.
*
* - `not like`: similar to the `like` operator except that `LIKE` is replaced with `NOT LIKE`
* in the generated condition.
*
* - `or not like`: similar to the `not like` operator except that `OR` is used to concatenate
* the `NOT LIKE` predicates.
* *
* @param array $condition the conditions that should be put in the WHERE part. * @param array $condition the conditions that should be put in the WHERE part.
* @return static the query object itself * @return static the query object itself
...@@ -224,7 +133,7 @@ trait QueryTrait ...@@ -224,7 +133,7 @@ trait QueryTrait
* Sets the ORDER BY part of the query. * Sets the ORDER BY part of the query.
* @param string|array $columns the columns (and the directions) to be ordered by. * @param string|array $columns the columns (and the directions) to be ordered by.
* Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array * Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array
* (e.g. `['id' => Query::SORT_ASC, 'name' => Query::SORT_DESC]`). * (e.g. `['id' => SORT_ASC, 'name' => SORT_DESC]`).
* The method will automatically quote the column names unless a column contains some parenthesis * The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression). * (which means the column contains a DB expression).
* @return static the query object itself * @return static the query object itself
...@@ -240,7 +149,7 @@ trait QueryTrait ...@@ -240,7 +149,7 @@ trait QueryTrait
* Adds additional ORDER BY columns to the query. * Adds additional ORDER BY columns to the query.
* @param string|array $columns the columns (and the directions) to be ordered by. * @param string|array $columns the columns (and the directions) to be ordered by.
* Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array * Columns can be specified in either a string (e.g. "id ASC, name DESC") or an array
* (e.g. `['id' => Query::SORT_ASC, 'name' => Query::SORT_DESC]`). * (e.g. `['id' => SORT_ASC, 'name' => SORT_DESC]`).
* The method will automatically quote the column names unless a column contains some parenthesis * The method will automatically quote the column names unless a column contains some parenthesis
* (which means the column contains a DB expression). * (which means the column contains a DB expression).
* @return static the query object itself * @return static the query object itself
...@@ -266,9 +175,9 @@ trait QueryTrait ...@@ -266,9 +175,9 @@ trait QueryTrait
$result = []; $result = [];
foreach ($columns as $column) { foreach ($columns as $column) {
if (preg_match('/^(.*?)\s+(asc|desc)$/i', $column, $matches)) { if (preg_match('/^(.*?)\s+(asc|desc)$/i', $column, $matches)) {
$result[$matches[1]] = strcasecmp($matches[2], 'desc') ? self::SORT_ASC : self::SORT_DESC; $result[$matches[1]] = strcasecmp($matches[2], 'desc') ? SORT_ASC : SORT_DESC;
} else { } else {
$result[$column] = self::SORT_ASC; $result[$column] = SORT_ASC;
} }
} }
return $result; return $result;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment