From b11957604125c57cf29a7e912279d5dc183ed4ed Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Fri, 17 Jan 2014 22:07:02 +0400 Subject: [PATCH 01/11] Fixes #2016: removed ability to declare scopes in ActiveRecord leaving it to ActiveQuery. Changed documentation accordingly. --- docs/guide/active-record.md | 102 +++++++++++++++++++++--------- framework/db/ActiveQuery.php | 2 +- framework/db/ActiveQueryTrait.php | 28 +------- 3 files changed, 74 insertions(+), 58 deletions(-) diff --git a/docs/guide/active-record.md b/docs/guide/active-record.md index 02d5c85716..9cf1d5b803 100644 --- a/docs/guide/active-record.md +++ b/docs/guide/active-record.md @@ -545,32 +545,60 @@ Finally when calling [[delete()]] to delete an ActiveRecord, we will have the fo 3. [[afterDelete()]]: will trigger an [[EVENT_AFTER_DELETE]] event -Scopes ------- +Custom scopes +------------- -A scope is a method that customizes a given [[ActiveQuery]] object. Scope methods are static and are defined -in the ActiveRecord classes. They can be invoked through the [[ActiveQuery]] object that is created -via [[find()]] or [[findBySql()]]. The following is an example: +When [[find()]] or [[findBySql()]] Active Record method is being called without parameters it returns an [[ActiveQuery]] +instance. This object holds all the parameters and conditions for a future query and also allows you to customize these +using a set of methods that are called scopes. By deafault there is a good set of such methods some of which we've +already used above: `where`, `orderBy`, `limit` etc. + +In many cases it is convenient to wrap extra conditions into custom scope methods. In order to do so you need two things. +First is creating a custom query class for your model. For example, a `Comment` may have a `CommentQuery`: ```php -class Comment extends \yii\db\ActiveRecord -{ - // ... +namespace app\models; - /** - * @param ActiveQuery $query - */ - public static function active($query) +import yii\db\ActiveQuery; + +class CommentQuery extends ActiveQuery +{ + public function active($state = true) { - $query->andWhere('status = 1'); + $this->andWhere(['active' => $state]); + return $this; } } - -$comments = Comment::find()->active()->all(); ``` -In the above, the `active()` method is defined in `Comment` while we are calling it -through `ActiveQuery` returned by `Comment::find()`. +Important points are: + +1. Class should extend from `yii\db\ActiveQuery` (or another `ActiveQuery` such as `yii\mongodb\ActiveQuery`). +2. A method should be `public` and should return `$this` in order to allow method chaining. It may accept parameters. +3. Check `ActiveQuery` methods that are very useful for modifying query conditions. + +The second step is to use `CommentQuery` instead of regular `ActiveQuery` for `Comment` model: + +``` +namespace app\models; + +use yii\db\ActiveRecord; + +class Comment extends ActiveRecord +{ + public static function createQuery() + { + return new CommentQuery(['modelClass' => get_called_class()]); + } +} +``` + +That's it. Now you can use your custom scope methods: + +```php +$comments = Comment::find()->active()->all(); +$inactiveComments = Comment::find()->active(false)->all(); +``` You can also use scopes when defining relations. For example, @@ -595,30 +623,44 @@ $posts = Post::find()->with([ ])->all(); ``` -Scopes can be parameterized. For example, we can define and use the following `olderThan` scope: +### Making it IDE-friendly + +In order to make your IDE autocomplete happy you can override return types for `one` and `all` methods like +the following: ```php -class Customer extends \yii\db\ActiveRecord +namespace app\models; + +import yii\db\ActiveQuery; + +class CommentQuery extends ActiveQuery { - // ... + /** + * Executes query and returns all results as an array. + * @param Connection $db the DB connection used to create the DB command. + * If null, the DB connection returned by [[modelClass]] will be used. + * @return array|Comment[] the query results. If the query results in nothing, an empty array will be returned. + */ + public function all($db = null) + { + parent::all($db); + } /** - * @param ActiveQuery $query - * @param integer $age + * Executes query and returns a single row of result. + * @param Connection $db the DB connection used to create the DB command. + * If null, the DB connection returned by [[modelClass]] will be used. + * @return Comment|array|null a single row of query result. Depending on the setting of [[asArray]], + * the query result may be either an array or an ActiveRecord object. Null will be returned + * if the query results in nothing. */ - public static function olderThan($query, $age = 30) + public function one($db = null) { - $query->andWhere('age > :age', [':age' => $age]); + parent::one($db); } } - -$customers = Customer::find()->olderThan(50)->all(); ``` -The parameters should follow after the `$query` parameter when defining the scope method, and they -can take default values like shown above. - - Transactional operations ------------------------ diff --git a/framework/db/ActiveQuery.php b/framework/db/ActiveQuery.php index 1731fc1f5b..df78e87994 100644 --- a/framework/db/ActiveQuery.php +++ b/framework/db/ActiveQuery.php @@ -60,7 +60,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface * Executes query and returns all results as an array. * @param Connection $db the DB connection used to create the DB command. * If null, the DB connection returned by [[modelClass]] will be used. - * @return array the query results. If the query results in nothing, an empty array will be returned. + * @return array|ActiveRecord[] the query results. If the query results in nothing, an empty array will be returned. */ public function all($db = null) { diff --git a/framework/db/ActiveQueryTrait.php b/framework/db/ActiveQueryTrait.php index fa24ed3e94..4444f3426e 100644 --- a/framework/db/ActiveQueryTrait.php +++ b/framework/db/ActiveQueryTrait.php @@ -31,32 +31,6 @@ trait ActiveQueryTrait */ 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 - * @throws \yii\base\InvalidCallException - * @return mixed the method return result - */ - public function __call($name, $params) - { - if (method_exists($this->modelClass, $name)) { - $method = new \ReflectionMethod($this->modelClass, $name); - if (!$method->isStatic() || !$method->isPublic()) { - throw new InvalidCallException("The scope method \"{$this->modelClass}::$name()\" must be public and static."); - } - 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. @@ -175,7 +149,7 @@ trait ActiveQueryTrait * Finds records corresponding to one or multiple relations and populates them into the primary models. * @param array $with a list of relations that this query should be performed with. Please * refer to [[with()]] for details about specifying this parameter. - * @param array $models the primary models (can be either AR instances or arrays) + * @param array|ActiveRecord[] $models the primary models (can be either AR instances or arrays) */ public function findWith($with, &$models) { From 53e96b29ca14844492de6e99edf03bb4e452af73 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Fri, 17 Jan 2014 22:22:49 +0400 Subject: [PATCH 02/11] Added note about scopes to upgrade guide --- docs/guide/upgrade-from-v1.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/guide/upgrade-from-v1.md b/docs/guide/upgrade-from-v1.md index 7eb66a83dc..af4a4de4fc 100644 --- a/docs/guide/upgrade-from-v1.md +++ b/docs/guide/upgrade-from-v1.md @@ -459,6 +459,8 @@ By default, ActiveRecord now only saves dirty attributes. In 1.1, all attributes are saved to database when you call `save()`, regardless of having changed or not, unless you explicitly list the attributes to save. +Scopes are now defined in a custom `ActiveQuery` class instead of model directly. + See [active record docs](active-record.md) for more details. From 0699eaadd5cfa15c0864e5d3f25848e9f6b5652b Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Fri, 17 Jan 2014 22:33:10 +0400 Subject: [PATCH 03/11] Fixed test breaks --- tests/unit/data/ar/Customer.php | 11 ++++++----- tests/unit/data/ar/CustomerQuery.php | 15 +++++++++++++++ tests/unit/data/ar/mongodb/Customer.php | 12 +++++++----- tests/unit/data/ar/mongodb/CustomerQuery.php | 15 +++++++++++++++ tests/unit/data/ar/sphinx/ArticleIndex.php | 13 ++++++------- tests/unit/data/ar/sphinx/ArticleIndexQuery.php | 15 +++++++++++++++ 6 files changed, 64 insertions(+), 17 deletions(-) create mode 100644 tests/unit/data/ar/CustomerQuery.php create mode 100644 tests/unit/data/ar/mongodb/CustomerQuery.php create mode 100644 tests/unit/data/ar/sphinx/ArticleIndexQuery.php diff --git a/tests/unit/data/ar/Customer.php b/tests/unit/data/ar/Customer.php index 2d9618a51f..0891b159be 100644 --- a/tests/unit/data/ar/Customer.php +++ b/tests/unit/data/ar/Customer.php @@ -1,6 +1,7 @@ hasMany(Order::className(), ['customer_id' => 'id'])->orderBy('id'); } - public static function active($query) - { - $query->andWhere('status=1'); - } - public function afterSave($insert) { ActiveRecordTest::$afterSaveInsert = $insert; ActiveRecordTest::$afterSaveNewRecord = $this->isNewRecord; parent::afterSave($insert); } + + public static function createQuery() + { + return new CustomerQuery(['modelClass' => get_called_class()]); + } } diff --git a/tests/unit/data/ar/CustomerQuery.php b/tests/unit/data/ar/CustomerQuery.php new file mode 100644 index 0000000000..89b9c9c93b --- /dev/null +++ b/tests/unit/data/ar/CustomerQuery.php @@ -0,0 +1,15 @@ +andWhere('status=1'); + } +} + \ No newline at end of file diff --git a/tests/unit/data/ar/mongodb/Customer.php b/tests/unit/data/ar/mongodb/Customer.php index 7b98fe6331..01f545f048 100644 --- a/tests/unit/data/ar/mongodb/Customer.php +++ b/tests/unit/data/ar/mongodb/Customer.php @@ -2,6 +2,8 @@ namespace yiiunit\data\ar\mongodb; +use yii\mongodb\ActiveQuery; + class Customer extends ActiveRecord { public static function collectionName() @@ -20,13 +22,13 @@ class Customer extends ActiveRecord ]; } - public static function activeOnly($query) - { - $query->andWhere(['status' => 2]); - } - public function getOrders() { return $this->hasMany(CustomerOrder::className(), ['customer_id' => '_id']); } + + public static function createQuery() + { + return new CustomerQuery(['modelClass' => get_called_class()]); + } } \ No newline at end of file diff --git a/tests/unit/data/ar/mongodb/CustomerQuery.php b/tests/unit/data/ar/mongodb/CustomerQuery.php new file mode 100644 index 0000000000..009b7b2db8 --- /dev/null +++ b/tests/unit/data/ar/mongodb/CustomerQuery.php @@ -0,0 +1,15 @@ +andWhere(['status' => 2]); + } +} + \ No newline at end of file diff --git a/tests/unit/data/ar/sphinx/ArticleIndex.php b/tests/unit/data/ar/sphinx/ArticleIndex.php index ed1073dcb7..66d6bebc15 100644 --- a/tests/unit/data/ar/sphinx/ArticleIndex.php +++ b/tests/unit/data/ar/sphinx/ArticleIndex.php @@ -1,8 +1,7 @@ andWhere('author_id=1'); - } - public function getSource() { return $this->hasOne(ArticleDb::className(), ['id' => 'id']); @@ -32,4 +26,9 @@ class ArticleIndex extends ActiveRecord { return $this->source->content; } + + public static function createQuery() + { + return new ArticleIndexQuery(['modelClass' => get_called_class()]); + } } \ No newline at end of file diff --git a/tests/unit/data/ar/sphinx/ArticleIndexQuery.php b/tests/unit/data/ar/sphinx/ArticleIndexQuery.php new file mode 100644 index 0000000000..19da67494b --- /dev/null +++ b/tests/unit/data/ar/sphinx/ArticleIndexQuery.php @@ -0,0 +1,15 @@ +andWhere('author_id=1'); + } +} + \ No newline at end of file From ed97632f53e8fe5fbccf8ea4720ac951aa0d5c9e Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Fri, 17 Jan 2014 23:01:13 +0400 Subject: [PATCH 04/11] Fixed scope method signatures --- tests/unit/data/ar/CustomerQuery.php | 5 +++-- tests/unit/data/ar/mongodb/CustomerQuery.php | 5 +++-- tests/unit/data/ar/sphinx/ArticleIndexQuery.php | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/unit/data/ar/CustomerQuery.php b/tests/unit/data/ar/CustomerQuery.php index 89b9c9c93b..6b1013452b 100644 --- a/tests/unit/data/ar/CustomerQuery.php +++ b/tests/unit/data/ar/CustomerQuery.php @@ -7,9 +7,10 @@ use yii\db\ActiveQuery; */ class CustomerQuery extends ActiveQuery { - public static function active($query) + public function active() { - $query->andWhere('status=1'); + $this->andWhere('status=1'); + return $this; } } \ No newline at end of file diff --git a/tests/unit/data/ar/mongodb/CustomerQuery.php b/tests/unit/data/ar/mongodb/CustomerQuery.php index 009b7b2db8..bf222b6d3d 100644 --- a/tests/unit/data/ar/mongodb/CustomerQuery.php +++ b/tests/unit/data/ar/mongodb/CustomerQuery.php @@ -7,9 +7,10 @@ use yii\mongodb\ActiveQuery; */ class CustomerQuery extends ActiveQuery { - public static function activeOnly($query) + public function activeOnly() { - $query->andWhere(['status' => 2]); + $this->andWhere(['status' => 2]); + return $this; } } \ No newline at end of file diff --git a/tests/unit/data/ar/sphinx/ArticleIndexQuery.php b/tests/unit/data/ar/sphinx/ArticleIndexQuery.php index 19da67494b..f5843f001d 100644 --- a/tests/unit/data/ar/sphinx/ArticleIndexQuery.php +++ b/tests/unit/data/ar/sphinx/ArticleIndexQuery.php @@ -7,9 +7,10 @@ use yii\sphinx\ActiveQuery; */ class ArticleIndexQuery extends ActiveQuery { - public static function favoriteAuthor($query) + public function favoriteAuthor() { - $query->andWhere('author_id=1'); + $this->andWhere('author_id=1'); + return $this; } } \ No newline at end of file From af385858c79e32d75d471e8222cdfd7238d4ba32 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Fri, 17 Jan 2014 23:24:31 +0400 Subject: [PATCH 05/11] Fixed tests for elasticsearch, mongo, redis --- tests/unit/data/ar/elasticsearch/Customer.php | 10 ++++++---- .../unit/data/ar/elasticsearch/CustomerQuery.php | 16 ++++++++++++++++ tests/unit/data/ar/mongodb/file/CustomerFile.php | 7 +++++-- .../data/ar/mongodb/file/CustomerFileQuery.php | 16 ++++++++++++++++ tests/unit/data/ar/redis/Customer.php | 11 ++++++----- tests/unit/data/ar/redis/CustomerQuery.php | 16 ++++++++++++++++ 6 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 tests/unit/data/ar/elasticsearch/CustomerQuery.php create mode 100644 tests/unit/data/ar/mongodb/file/CustomerFileQuery.php create mode 100644 tests/unit/data/ar/redis/CustomerQuery.php diff --git a/tests/unit/data/ar/elasticsearch/Customer.php b/tests/unit/data/ar/elasticsearch/Customer.php index 22d2c09228..4ffc5f6e22 100644 --- a/tests/unit/data/ar/elasticsearch/Customer.php +++ b/tests/unit/data/ar/elasticsearch/Customer.php @@ -35,10 +35,7 @@ class Customer extends ActiveRecord return $this->hasMany(Order::className(), array('customer_id' => 'id'))->orderBy('create_time'); } - public static function active($query) - { - $query->andWhere(array('status' => 1)); - } + public function afterSave($insert) { @@ -67,4 +64,9 @@ class Customer extends ActiveRecord ]); } + + public static function createQuery() + { + return new CustomerQuery(['modelClass' => get_called_class()]); + } } diff --git a/tests/unit/data/ar/elasticsearch/CustomerQuery.php b/tests/unit/data/ar/elasticsearch/CustomerQuery.php new file mode 100644 index 0000000000..5df080f0b1 --- /dev/null +++ b/tests/unit/data/ar/elasticsearch/CustomerQuery.php @@ -0,0 +1,16 @@ +andWhere(array('status' => 1)); + return $this; + } +} + \ No newline at end of file diff --git a/tests/unit/data/ar/mongodb/file/CustomerFile.php b/tests/unit/data/ar/mongodb/file/CustomerFile.php index a396477825..20073f8fbc 100644 --- a/tests/unit/data/ar/mongodb/file/CustomerFile.php +++ b/tests/unit/data/ar/mongodb/file/CustomerFile.php @@ -2,6 +2,9 @@ namespace yiiunit\data\ar\mongodb\file; +use yii\mongodb\file\ActiveQuery; +use yiiunit\data\ar\redis\CustomerQuery; + class CustomerFile extends ActiveRecord { public static function collectionName() @@ -20,8 +23,8 @@ class CustomerFile extends ActiveRecord ); } - public static function activeOnly($query) + public static function createQuery() { - $query->andWhere(['status' => 2]); + return new CustomerQuery(['modelClass' => get_called_class()]); } } \ No newline at end of file diff --git a/tests/unit/data/ar/mongodb/file/CustomerFileQuery.php b/tests/unit/data/ar/mongodb/file/CustomerFileQuery.php new file mode 100644 index 0000000000..6adbe801f2 --- /dev/null +++ b/tests/unit/data/ar/mongodb/file/CustomerFileQuery.php @@ -0,0 +1,16 @@ +andWhere(['status' => 2]); + return $this; + } +} + \ No newline at end of file diff --git a/tests/unit/data/ar/redis/Customer.php b/tests/unit/data/ar/redis/Customer.php index 63143ffe56..8e5a1b8d6c 100644 --- a/tests/unit/data/ar/redis/Customer.php +++ b/tests/unit/data/ar/redis/Customer.php @@ -2,6 +2,7 @@ namespace yiiunit\data\ar\redis; +use yii\redis\ActiveQuery; use yiiunit\extensions\redis\ActiveRecordTest; class Customer extends ActiveRecord @@ -24,15 +25,15 @@ class Customer extends ActiveRecord return $this->hasMany(Order::className(), ['customer_id' => 'id']); } - public static function active($query) - { - $query->andWhere(['status' => 1]); - } - public function afterSave($insert) { ActiveRecordTest::$afterSaveInsert = $insert; ActiveRecordTest::$afterSaveNewRecord = $this->isNewRecord; parent::afterSave($insert); } + + public static function createQuery() + { + return new CustomerQuery(['modelClass' => get_called_class()]); + } } \ No newline at end of file diff --git a/tests/unit/data/ar/redis/CustomerQuery.php b/tests/unit/data/ar/redis/CustomerQuery.php new file mode 100644 index 0000000000..47d69fb95d --- /dev/null +++ b/tests/unit/data/ar/redis/CustomerQuery.php @@ -0,0 +1,16 @@ +andWhere(['status' => 1]); + return $this; + } +} + \ No newline at end of file From 87d42e9f37fe5dda2aeaf0568878589f0937a69a Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Fri, 17 Jan 2014 23:37:39 +0400 Subject: [PATCH 06/11] Fixed wrong namespace --- tests/unit/data/ar/mongodb/file/CustomerFile.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/unit/data/ar/mongodb/file/CustomerFile.php b/tests/unit/data/ar/mongodb/file/CustomerFile.php index 20073f8fbc..db70acc766 100644 --- a/tests/unit/data/ar/mongodb/file/CustomerFile.php +++ b/tests/unit/data/ar/mongodb/file/CustomerFile.php @@ -2,8 +2,7 @@ namespace yiiunit\data\ar\mongodb\file; -use yii\mongodb\file\ActiveQuery; -use yiiunit\data\ar\redis\CustomerQuery; +use yiiunit\data\ar\mongodb\CustomerQuery; class CustomerFile extends ActiveRecord { From a19f499cbf458b27045f6162a8733f78aebe250d Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Sat, 18 Jan 2014 16:54:58 +0400 Subject: [PATCH 07/11] Added missing return to docs --- docs/guide/active-record.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guide/active-record.md b/docs/guide/active-record.md index 9cf1d5b803..537bdd967d 100644 --- a/docs/guide/active-record.md +++ b/docs/guide/active-record.md @@ -643,7 +643,7 @@ class CommentQuery extends ActiveQuery */ public function all($db = null) { - parent::all($db); + return parent::all($db); } /** @@ -656,7 +656,7 @@ class CommentQuery extends ActiveQuery */ public function one($db = null) { - parent::one($db); + return parent::one($db); } } ``` From f21d2ce757432b88e7c29ec64badff9f04eeedd6 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Sun, 19 Jan 2014 03:44:33 +0400 Subject: [PATCH 08/11] Better phpdoc --- framework/db/BaseActiveRecord.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/db/BaseActiveRecord.php b/framework/db/BaseActiveRecord.php index c8d199b2b4..ff16476b87 100644 --- a/framework/db/BaseActiveRecord.php +++ b/framework/db/BaseActiveRecord.php @@ -102,7 +102,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface * - an array of name-value pairs: query by a set of column values and return a single record matching all of them. * - null: return a new [[ActiveQuery]] object for further query purpose. * - * @return ActiveQuery|ActiveRecord|null When `$q` is null, a new [[ActiveQuery]] instance + * @return ActiveQuery|static|null When `$q` is null, a new [[ActiveQuery]] instance * is returned; when `$q` is a scalar or an array, an ActiveRecord object matching it will be * returned (null will be returned if there is no matching). * @throws InvalidConfigException if the AR class does not have a primary key From 9faf0c5a091720630a034c5dc3bcc9c6aed0fceb Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Sun, 19 Jan 2014 03:44:57 +0400 Subject: [PATCH 09/11] Updated Making it IDE-friendly section in AR scopes doc --- docs/guide/active-record.md | 49 ++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/docs/guide/active-record.md b/docs/guide/active-record.md index 537bdd967d..093c22cf9c 100644 --- a/docs/guide/active-record.md +++ b/docs/guide/active-record.md @@ -625,8 +625,8 @@ $posts = Post::find()->with([ ### Making it IDE-friendly -In order to make your IDE autocomplete happy you can override return types for `one` and `all` methods like -the following: +In order to make your IDE autocomplete happy you can override return types for `one` and `all` methods of your query +object like the following: ```php namespace app\models; @@ -636,10 +636,8 @@ import yii\db\ActiveQuery; class CommentQuery extends ActiveQuery { /** - * Executes query and returns all results as an array. - * @param Connection $db the DB connection used to create the DB command. - * If null, the DB connection returned by [[modelClass]] will be used. - * @return array|Comment[] the query results. If the query results in nothing, an empty array will be returned. + * @inheritdoc + * @return array|Comment[] */ public function all($db = null) { @@ -647,12 +645,8 @@ class CommentQuery extends ActiveQuery } /** - * Executes query and returns a single row of result. - * @param Connection $db the DB connection used to create the DB command. - * If null, the DB connection returned by [[modelClass]] will be used. - * @return Comment|array|null a single row of query result. Depending on the setting of [[asArray]], - * the query result may be either an array or an ActiveRecord object. Null will be returned - * if the query results in nothing. + * @inheritdoc + * @return Comment|array|null */ public function one($db = null) { @@ -661,6 +655,37 @@ class CommentQuery extends ActiveQuery } ``` +Then override your model methods: + +```php +namespace app\models; + +use yii\db\ActiveRecord; + +class Comment extends ActiveRecord +{ + /** + * @inheritdoc + * @return CustomerQuery + */ + public function findBySQL($sql, $params = []) + { + return parent::findBySQL($sql, $params); + } + + /** + * @inheritdoc + * @return null|static|CustomerQuery + */ + public function find($q = null) + { + return parent::find($q); + } +} +``` + +Note that it can be done via `@method` tag but, unfortunitely [IDE support isn't good enough](http://youtrack.jetbrains.com/issue/WI-17404). + Transactional operations ------------------------ From 28986f984c7ac6e085d2a18392ac8007f5ceb674 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Sun, 19 Jan 2014 04:03:30 +0400 Subject: [PATCH 10/11] Changed IDE-specific method overrides to @method --- docs/guide/active-record.md | 70 +++++++++---------------------------- 1 file changed, 17 insertions(+), 53 deletions(-) diff --git a/docs/guide/active-record.md b/docs/guide/active-record.md index 093c22cf9c..b66b0f1223 100644 --- a/docs/guide/active-record.md +++ b/docs/guide/active-record.md @@ -625,66 +625,30 @@ $posts = Post::find()->with([ ### Making it IDE-friendly -In order to make your IDE autocomplete happy you can override return types for `one` and `all` methods of your query -object like the following: +In order to make most modern IDE autocomplete happy you need to override return types for some methods of both model +and query like the following: ```php -namespace app\models; - -import yii\db\ActiveQuery; - -class CommentQuery extends ActiveQuery -{ - /** - * @inheritdoc - * @return array|Comment[] - */ - public function all($db = null) - { - return parent::all($db); - } - - /** - * @inheritdoc - * @return Comment|array|null - */ - public function one($db = null) - { - return parent::one($db); - } -} -``` - -Then override your model methods: - -```php -namespace app\models; - -use yii\db\ActiveRecord; - +/** + * @method \app\models\CommentQuery|static|null find($q = null) static + * @method \app\models\CommentQuery findBySql($sql, $params = []) static + */ class Comment extends ActiveRecord { - /** - * @inheritdoc - * @return CustomerQuery - */ - public function findBySQL($sql, $params = []) - { - return parent::findBySQL($sql, $params); - } - - /** - * @inheritdoc - * @return null|static|CustomerQuery - */ - public function find($q = null) - { - return parent::find($q); - } + // ... } ``` -Note that it can be done via `@method` tag but, unfortunitely [IDE support isn't good enough](http://youtrack.jetbrains.com/issue/WI-17404). +```php +/** + * @method \app\models\Comment|array|null one($db = null) + * @method \app\models\Comment[]|array all($db = null) + */ +class CommentQuery extends ActiveQuery +{ + // ... +} +``` Transactional operations ------------------------ From 504fc76f5ca927f65fa14af48570d9931981c41b Mon Sep 17 00:00:00 2001 From: Klimov Paul Date: Tue, 21 Jan 2014 21:39:22 +0200 Subject: [PATCH 11/11] Unit test for yii\mongodb\file\ActiveRecord fixed --- tests/unit/data/ar/mongodb/file/CustomerFile.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/unit/data/ar/mongodb/file/CustomerFile.php b/tests/unit/data/ar/mongodb/file/CustomerFile.php index db70acc766..40da8bf5d8 100644 --- a/tests/unit/data/ar/mongodb/file/CustomerFile.php +++ b/tests/unit/data/ar/mongodb/file/CustomerFile.php @@ -2,8 +2,6 @@ namespace yiiunit\data\ar\mongodb\file; -use yiiunit\data\ar\mongodb\CustomerQuery; - class CustomerFile extends ActiveRecord { public static function collectionName() @@ -24,6 +22,6 @@ class CustomerFile extends ActiveRecord public static function createQuery() { - return new CustomerQuery(['modelClass' => get_called_class()]); + return new CustomerFileQuery(['modelClass' => get_called_class()]); } } \ No newline at end of file