Yii2: Suggestion for yii\db\ActiveQuery, overridable finish() function

Created on 11 May 2017  路  5Comments  路  Source: yiisoft/yii2

Recently I鈥檝e met with the problem when I needed to apply some default filter to all queries for the given model, and it was solved quite easily
i.e always get active Products

class ProductQuery extends \yii\db\ActiveQuery
{
    public function init()
    {
        parent::init();
        $this->active(); // implementation is like $this->andWhere..
    }

    ...
}

But, assume that in some exceptional cases we need to fetch non-active Products too. In that case we cannot cancel the filters applied in init() stage, so I suppose that it would've been better if there'd been some "finish()" or "beforeExecute()" like method, that will be called right after anonymous Query function is executed.

So that: (Only exemplary)

class ProductQuery extends \yii\db\ActiveQuery
{
    public $isActive = true;

    public function finish()
    {
        if($this->isActive) {
            $this->active;
        }
        parent::finish();
    }
    ...
}

.. and i.e. while finding Shops, we can want to fetch all Products (non-actives too)

$shops = Shop::find()
        ->joinWith(['products' => function(ProductQuery $query) {
            $query->isActive = false;
        }]);

and in other cases we always fetch active Product only

In fact, I could not find a way to apply filters in Queries, depending on values in their properties (assuming that we pass them in anonymous functions). Of cource, we could write those filters in each of the queries, however it becomes difficult to maintain as project grows.

Maybe there is a better solution (without even touching the source code), and my proposal is all wrong.. If so, I would be grateful, if anyone shows me how it's done. Thanks

| Q | A
| ---------------- | ---
| Yii version | 2.0.6
| PHP version | 7.0
| Operating system | windows

question

All 5 comments

You can always call Query::where([]) to reset alredy applied search conditions like default scope.

Thank you for your question.
In order for this issue tracker to be effective, it should only contain bug reports and feature requests.

We advise you to use our community driven resources:

If you are confident that there is a bug in the framework, feel free to provide information on how to reproduce it. This issue will be closed for now.

_This is an automated comment, triggered by adding the label question._

But assuming that you have multiple where conditions, it will reset them all, and you will have to write them again in anonymous function, which make Query::where([]) not a good solution at all

I would recommend to do that on AR level:

public static function find()
{
    return parent::find()->active();
}

public static function findUnrestricted()
{
    return parent::find();
}

and use findUnrestricted() or whatever you call it in the special cases that do not have the limitation to active records.

Yeah, this one will work when you call findUnrestricted() for the given model.
But when the model is used in relation and joined with with() or joinWith(), it will use standard find() method

Was this page helpful?
0 / 5 - 0 ratings