Yii2 зарелизился не так давно, и пока документация не полная, а рецепты в интернете не всегда верные, приходится через страдания разбираться в фрэймворке.
Проблема default scope в Yii2 существует уже больше года, еще с того времени, как Yii2 был в бета версии. Соответственно при поиске нас кидает на различные обсуждения, среди которых преобладает кривое решение. Этот пост должен решить данную проблему.
Решение, которое преобладает, выглядит так:
<Не используйте этот код>
namespace appcomponents;
class ActiveRecord extends yiidbActiveRecord
{
public static function find()
{
return parent::find()->andWhere(['active' => 1]);
}
}
</Не используйте этот код>
То-есть добавляем условие прямо в метод.
Но при наследовании нас ждут проблемы, если мы заходим добавить обычный scope или default scope.
Пример добавления scope из документации:
namespace appmodels;
use yiidbActiveRecord;
use yiidbActiveQuery;
class Comment extends ActiveRecord
{
public static function find()
{
return new CommentQuery(get_called_class());
}
}
class CommentQuery extends ActiveQuery
{
public function active($state = true)
{
return $this->andWhere(['active' => $state]);
}
}
Метод find наследуемого ActiveRecord будет затерт. И, к сожалению, именно это решение находится в поиске и ведет на гитхаб yii2.
Верное решение для default scope
Нужно создать свой ActiveQuery, и возвращать его в методе find. Так-же в этом ActiveQuery можно прописывать другие scopes, как это описано в мануале.
namespace appcomponents;
class ActiveRecord extends yiidbActiveRecord
{
public static function find()
{
return new ActiveQuery(get_called_class());
}
}
namespace appcomponents;
class ActiveQuery extends yiidbActiveQuery
{
public function init()
{
parent::init();
$modelClass = $this->modelClass;
$tableName = $modelClass::tableName();
$this->andWhere(['active' => 1]);
}
}
Если мы заходим в модели отнаследовать ActiveRecord, мы будем иметь доступ ко всем scopes, а если захотим добавить еще default scope или обычные scopes, просто нужно наследоваться от нашего ActiveQuery.