Yii Framework Forum: Disable the default scope of a model - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Disable the default scope of a model Rate Topic: ***** 3 Votes

#1 User is offline   yoshi 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 170
  • Joined: 28-February 09
  • Location:Germany

Posted 04 October 2009 - 06:21 AM

Hi,

this tip is emerged from this topic with Mikes great idea to put it in a simple behavior.

So, if you have a defaultScope (e.g. for hiding records with a soft deletion) and you want to disable this default scope in some particular cases (e.g. an admin page where soft deleted records could be undeleted) you may add a behavior like the following:
<?php
class DisableDefaultScopeBehavior extends CActiveRecordBehavior
{
    private $_defaultScopeDisabled = false; // Flag - whether defaultScope is disabled or not

    public function disableDefaultScope()
    {
          $this->_defaultScopeDisabled = true;
          return $this->Owner;
    }

    public function getDefaultScopeDisabled() {
        return $this->_defaultScopeDisabled;
    }

}
?>


inside your model override the defaultScope() function like this:

    public function defaultScope()
    {
        return $this->getDefaultScopeDisabled() ?
            array() :
            array( 
                // Your default scope goes here e.g.
                // 'condition' => 'deleted=0' 
            ); 
    }


now you can call your model like this to disable the default scope:

MyModel::model()->disableDefaultScope()->findAll();


Have fun and thanks to Mike!

Cheers!

TAKE CARE: I don't know why, but this editor seems to make the 'behavior'-part of the classnames lowercase... of course they start with an uppercase 'B'.
0

#2 User is offline   tun001757 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 1
  • Joined: 01-December 09

Posted 14 December 2009 - 09:22 AM

how to attach this behavior to a model? where to put this behavior file? thank you
0

#3 User is offline   Extak 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 4
  • Joined: 02-February 10
  • Location:Brno, Czech Republic

Posted 15 October 2010 - 05:07 AM

This is realy useful if you call $model->find() method. But did anybody known solution if you need same behavior on related models? Example:

class Category extends CActiveRecord{
...
public function relations(){
    return array(
        ...
        'users'=>array(sefl::HAS_MANY, 'User', 'category_id'),
        ...
    );
} 
...
}

class User extends CActiveRecord{
...
    public function defaultBehavior(){
        ... some condition ...
    }
...
}

// Need get users without default scope of User class
$category->users

0

#4 User is offline   Binc 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 13
  • Joined: 11-January 12

Posted 12 January 2012 - 05:23 PM

Thanks Yoshi, I needed that for the very purpose you mentioned: soft deletes and the possibility to watch the "archive".

I didn't put it in a behaviour, though, but in the myProjectActiveRecord class which instances all my models and which I also use for the (soft) global beforeDelete(). That's partly because I'm not too familiar with behaviours and partly because it saves me from adding the behaviour to all my models. It works fine, but I might be doing things "against good practices".

Anyway, this is how I put it in. Any (mild) critisism is welcome.

abstract class MyProjectActiveRecord extends CActiveRecord
{
	/**
	* Switch off the default scope
	*/
	private $_defaultScopeDisabled = false; // Flag - whether defaultScope is disabled or not
	public function disableDefaultScope()
	{
		$this->_defaultScopeDisabled = true;
		return $this;    // not $this->Owner
	}
	public function getDefaultScopeDisabled() 
        {
		return $this->_defaultScopeDisabled;
	}
        etc...

0

#5 User is offline   guedalia 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 2
  • Joined: 19-November 12

Posted 19 November 2012 - 01:40 PM

View Postyoshi, on 04 October 2009 - 06:21 AM, said:

now you can call your model like this to disable the default scope:

MyModel::model()->disableDefaultScope()->findAll();



I noticed an issue (bug?) with using this implementation and wanted to bring it up for discussion.

If you use the above and perform a find, like this:

MyModel::model()->disableDefaultScope()->find($condition);


Then, elsewhere you do the following:

MyModel::model()->find($condition);


The default scope will STILL be disabled.

I am not sure, but think this is because it (find) shares an instance.
I thought I saw somewhere that this is not the case of findAll.

The solution I found was to reset the flag to false, prior to returning the default scope.

Comments and feedback welcome.
0

#6 User is offline   Wil W 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 1
  • Joined: 19-December 12

Posted 19 December 2012 - 11:09 AM

Just a note for future searchers that there is now a resetScope() function.

So one can just do:

MyModel::model()->resetScope()->findAll();


This will reset all scopes including the default (use resetScope(FALSE) to leave the default scope in place.)

Docs:
http://www.yiiframew...setScope-detail
2

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users