-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
Db traits #1097
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Db traits #1097
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
4653526
moved common parts of db ActiveRelation and Query to traits
cebe 0146596
add relationClassName to AR to allow different relation classes
cebe 3130aad
fixed conflicting property declaration
cebe b8e31d5
renamed AR trait classes
cebe c8c7f59
Merge branch 'master' into db-traits
cebe 6533897
refactored ActiveRecord classes to use Interfaces and traits
cebe 9448c3d
added unit tests for active dataprovider and fixed query tests
cebe ced7ee1
dataprovider: reset orderBy when counting
cebe 51faa62
updated interface and trait php-doc in yii\ar
cebe 1acdbb7
moved indexBy() trait -> interface + removed findWith from interface
cebe 8250cfb
reverted change of count() signature
cebe File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| <?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 query 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); | ||
|
|
||
| /** | ||
| * 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 or model data. The signature of the callable should be: | ||
| * | ||
| * ~~~ | ||
| * // $model is an AR instance when `asArray` is false, | ||
| * // or an array of column values when `asArray` is true. | ||
| * function ($model) | ||
| * { | ||
| * // return the index value corresponding to $model | ||
| * } | ||
| * ~~~ | ||
| * | ||
| * @return static the query object itself | ||
| */ | ||
| public function indexBy($column); | ||
|
|
||
| /** | ||
| * 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(); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,201 @@ | ||
| <?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\ActiveRecord; | ||
|
|
||
| /** | ||
| * ActiveQueryTrait implements the common methods and properties for active record query classes. | ||
| * | ||
| * @author Qiang Xue <qiang.xue@gmail.com> | ||
| * @author Carsten Brandt <mail@cebe.cc> | ||
| * @since 2.0 | ||
| */ | ||
| trait ActiveQueryTrait | ||
| { | ||
| /** | ||
| * @var string the name of the ActiveRecord class. | ||
| */ | ||
| public $modelClass; | ||
| /** | ||
| * @var array list of relations that this query should be performed with | ||
| */ | ||
| public $with; | ||
| /** | ||
| * @var boolean whether to return each record as an array. If false (default), an object | ||
| * of [[modelClass]] will be created to represent each record. | ||
| */ | ||
| public $asArray; | ||
|
|
||
|
|
||
| /** | ||
| * PHP magic method. | ||
| * This method allows calling static method defined in [[modelClass]] via this query object. | ||
| * It is mainly implemented for supporting the feature of scope. | ||
| * @param string $name the method name to be called | ||
| * @param array $params the parameters passed to the method | ||
| * @return mixed the method return result | ||
| */ | ||
| public function __call($name, $params) | ||
| { | ||
| if (method_exists($this->modelClass, $name)) { | ||
| array_unshift($params, $this); | ||
| call_user_func_array([$this->modelClass, $name], $params); | ||
| return $this; | ||
| } else { | ||
| return parent::__call($name, $params); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * 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) | ||
| { | ||
| $this->asArray = $value; | ||
| return $this; | ||
| } | ||
|
|
||
| /** | ||
| * 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() | ||
| { | ||
| $this->with = func_get_args(); | ||
| if (isset($this->with[0]) && is_array($this->with[0])) { | ||
| // the parameter is given as an array | ||
| $this->with = $this->with[0]; | ||
| } | ||
| return $this; | ||
| } | ||
|
|
||
| /** | ||
| * Converts found rows into model instances | ||
| * @param array $rows | ||
| * @return array|ActiveRecord[] | ||
| */ | ||
| private function createModels($rows) | ||
| { | ||
| $models = []; | ||
| if ($this->asArray) { | ||
| if ($this->indexBy === null) { | ||
| return $rows; | ||
| } | ||
| foreach ($rows as $row) { | ||
| if (is_string($this->indexBy)) { | ||
| $key = $row[$this->indexBy]; | ||
| } else { | ||
| $key = call_user_func($this->indexBy, $row); | ||
| } | ||
| $models[$key] = $row; | ||
| } | ||
| } else { | ||
| /** @var ActiveRecord $class */ | ||
| $class = $this->modelClass; | ||
| if ($this->indexBy === null) { | ||
| foreach ($rows as $row) { | ||
| $models[] = $class::create($row); | ||
| } | ||
| } else { | ||
| foreach ($rows as $row) { | ||
| $model = $class::create($row); | ||
| if (is_string($this->indexBy)) { | ||
| $key = $model->{$this->indexBy}; | ||
| } else { | ||
| $key = call_user_func($this->indexBy, $model); | ||
| } | ||
| $models[$key] = $model; | ||
| } | ||
| } | ||
| } | ||
| return $models; | ||
| } | ||
|
|
||
| /** | ||
| * @param ActiveRecord[] $models | ||
| * @param array $with | ||
| */ | ||
| private function populateRelations(&$models, $with) | ||
| { | ||
| $primaryModel = new $this->modelClass; | ||
| $relations = $this->normalizeRelations($primaryModel, $with); | ||
| foreach ($relations as $name => $relation) { | ||
| if ($relation->asArray === null) { | ||
| // inherit asArray from primary query | ||
| $relation->asArray = $this->asArray; | ||
| } | ||
| $relation->findWith($name, $models); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @param ActiveRecord $model | ||
| * @param array $with | ||
| * @return ActiveRelationInterface[] | ||
| */ | ||
| private function normalizeRelations($model, $with) | ||
| { | ||
| $relations = []; | ||
| foreach ($with as $name => $callback) { | ||
| if (is_integer($name)) { | ||
| $name = $callback; | ||
| $callback = null; | ||
| } | ||
| if (($pos = strpos($name, '.')) !== false) { | ||
| // with sub-relations | ||
| $childName = substr($name, $pos + 1); | ||
| $name = substr($name, 0, $pos); | ||
| } else { | ||
| $childName = null; | ||
| } | ||
|
|
||
| if (!isset($relations[$name])) { | ||
| $relation = $model->getRelation($name); | ||
| $relation->primaryModel = null; | ||
| $relations[$name] = $relation; | ||
| } else { | ||
| $relation = $relations[$name]; | ||
| } | ||
|
|
||
| if (isset($childName)) { | ||
| $relation->with[$childName] = $callback; | ||
| } elseif ($callback !== null) { | ||
| call_user_func($callback, $relation); | ||
| } | ||
| } | ||
| return $relations; | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| <?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. | ||
| * | ||
| * A class implementing this interface should also use [[ActiveRelationTrait]]. | ||
| * | ||
| * @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); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why
yii\db\ActiveRecordis needed?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as in ActiveRelationTrait