Activequery And Old Defaultscope

Hi!

I’m trying to use an ActiveQuery class to implement something like old defaultScope.

overwriting init method and setting the "default" where condition seems to work… until you call Model::find(1)…

when you pass the key to find method… it always overwrites the where condition.

Is there a better way to do that?

Thanks in advance!

How about this?




        /**

	 * Creates an [[ActiveQuery]] instance.

	 * 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

	 * written for querying `Customer` purpose.)

	 * @return ActiveQuery the newly created [[ActiveQuery]] instance.

	 */

	public static function createQuery()

	{

		return new ActiveQuery(['modelClass' => get_called_class()]);

	}



It’s exactly what I did.




   		public static function createQuery()

	{

		return new MyActiveQuery(['modelClass' => get_called_class()]);

	}



then in MyActiveQuery




public function init()

{

    parent::init();

    $condition = "AND .... .... ..";

    $this->where($condition);

}



It works until you call MyActiveRecord::find(1) 'cos it always overwrites $this->where

EDIT:

in this way It works both with MyActiveRecord::find(1) and ActiveRecord (it uses query->all() and without filters it doesn’t call where() function) but I have to overwrite 2 methods




 public function init()

    {

        parent::init();

        $this->andWhere($this->myDefaultCondition());

    }

    

    public function where($condition, $params = [])

    {

        parent::where($condition, $params);

        return $this->andWhere($this->myDefaultCondition());

    }



Oh I misunderstood what you did.

But why are you putting this in ActiveQuery instead of ActiveRecord? If you did the latter, then the solution is much easier.

Could you give me an example please?

For example I’d like to filter only record with column ‘active=1’. Exactly like old defaultScope.

Something like this:




class MyActiveRecord extends \yii\db\ActiveRecord {


        /**

         * @inheritdoc

         */

        public static function createQuery()

        {

                $condition = ["active" => 1];

                $query = new \yii\db\ActiveQuery(['modelClass' => get_called_class()]);

                return $query->where($condition);

        }


}



Same problem.

It creates Query object and then set where condition.

if you call MyActiveRecord::find(1) that condition will be substituted by primary key condition only

Did you try it? Because it works for me.

Not only that, but the ActiveRecord::find() function actually calls the createQuery() function. So it shouldn’t be substituting it, but instead adding to it.




public static function find($q = null)

	{

		$query = static::createQuery();

		if (is_array($q)) {

			return $query->where($q)->one();

		} elseif ($q !== null) {

			// query by primary key

			$primaryKey = static::primaryKey();

			if (isset($primaryKey[0])) {

				return $query->where([$primaryKey[0] => $q])->one();

			} else {

				throw new InvalidConfigException(get_called_class() . ' must have a primary key.');

			}

		}

		return $query;

	}



For example

ID, name, active

1, John, 1

2, Peter, 0

3, Mary, 0

set the where during createQuery to ‘active=1’ as in your example


MyActiveRecord::find() // returns 1 record (John) --> right

MyActiveRecord::find(2) // returns 1 record (Peter) --> wrong(?!?) 


public static function find($q = null) 

{

.....

$query->where([$primaryKey[0] => $q])->one() // overwrites 'active=1' condition

......

}

Ok, I see now - the problem is specifically with the find() function. In that case, you should be able to just override the find() itself (in addition to the createQuery()).

I asked same question in github https://github.com/yiisoft/yii2/issues/1469 and got the following answer:

Yes in Yii2 is dropped, because this method make many problems.

You can simple add default scope, e.q

class Post extends ActiveRecord

{

    public static function find($q = null)


    {


            return parent::find()->defaultOrder();


    }


    public static function defaultOrder($query)


    {


          $query->order('id desc');


    }

}

It works perfect and is more flexibel than the old default scpope

Thank U very much! I’ll try it

It didn’t work for where conditions

Anyway I reported a bug that has already been solved yesterday