Disable defaultScope / add exclusive scope

Hi,

well, i was searching for something to disable the defaultScope - without success.

So for my purpose a simple possibility to disable the defaultScope would be enough, but furthermore i would appreciate having something like with_exclusive_scope like RoR has which ignores all previous scopes.

I did it a quick and dirty way by adding following function to CActiveRecord


    public function withExclusiveScope()

    {

        $this->_c = new CDbCriteria();

        return $this;

    }

and calling it like


MyModel::model()->withExclusiveScope()->findbyPk($id!==null ? $id : $_GET['mid']);

But modifying core code is evil and i wanna keep my soul! ;)

Any opinions?

Regards

Should be possible to implement as behavior:

http://www.yiiframework.com/doc/cookbook/30/

Hi Mike,

i can’t see this possibility… :blink:

Because the defaultScope is always applied to the criteria when getDbCriteria() is called for the first time where it creates the internal CDbCriteria object.

Would you explain your thoughts how to solve this in a bahavior more in detail please?!

Best Regards

Oh, you’re right, of course. Didn’t look close enough at your code example.

Another solution might be to extend AR and use that as base class for your records. But even that would require to add some logic to defaultScope() every time.


class MyActiveRecord extends CActiveRecord

{

    private $_es=false; // flag for exclusive scope


    public function withExclusiveScope()

    {

      $this->_es=true;

      return $this;

    }


    public function getIsExclusiveScope() {

      return $this->_es;

    }

}

Then in your actual records:


class SomeRecord extends MyActiveRecord

{

    // ...


    public function defaultScope()

    {

        return $this->getIsExclusiveScope() ?

            array() :

            array( /* your default scope conditions here */ ); 

    }

}

As always: i didn’t test this :)

Edit:

Oh, and this time i think this solution can be implemented as behavior, too.

Default scope is a usual approach when logical deletion is implemented, so outdated rows will never be loaded. It is also useful when you want to restrict users from accessing other people’s content.

If you want to disable a scope in some cases, why would you want it to be default anyway?

@Mike

Thank you, this is a way it could be done. But (of course) i would prefer to have this without extending AR, because i think it’s nothing exceptional which is only useable for my special task…

Ahm, but how?

You’re absolutly right, but let’s take look at the case of soft deleted records: no one should see or use them, ok, so it would be more DRY to use a default scope, right?! But e.g. for administrative purpose it would be interesting to have a view where you can see all deleted records maybe with an option to undelete them. It’s not acceptable to tell the admin “well, go ahead and use the sql command line to undelete a record” or something like this.

Know what i mean?!

Regards

Actually it should be as simple as this: :)


class ExclusiveScope extends CActiveRecordBehavior

{

    private $_es=false; // flag for exclusive scope


    public function withExclusiveScope()

    {

      $this->_es=true;

      return $this->Owner;

    }


    public function getIsExclusiveScope() {

      return $this->_es;

    }

}


class SomeRecord extends MyActiveRecord

{

    // ...


    public function behaviors()

    {

        return array(

            'ExclusiveScope' => array('class'=>'ExclusiveScope')

        );

    }


    public function defaultScope()

    {

        return $this->getIsExclusiveScope() ?

            array() :

            array( /* your default scope conditions here */ ); 

    }

}

@Mike

Ok, i see what you mean. But unfortunately i would still need to extend CActiveRecord :(

But anyway thanks for your prompt help and ideas - like always ;)

Why that? All you should need is to add the behavior above.

Damn it, your absolutly right! Maybe i was cross-eyed but your idea works great! :)

This is definitely a better solution than in my first post!

Thank you Mike!

But nevertheless this ‘Feature Request’ is still pending, because Mikes solution works very well for me but it’s rather a defaultScope-switch than an exclusive scope.

Sure, your feature request is valid, we’ll work on it after higher priority tasks, hope you understand.

For administration it might be even better to use database access objects.