Running into a serious problem with how the scopes are set up in Yii. Perhaps I’m not understanding things, so I’ll explain what I’m doing and what I think is going on.
For a simple example if I want to display two separate grid views implemented with CActiveDataProvider on my view. One grid view shows active users and one shows inactive users. In my user class I have this handy scoping function:
public function whereActive($active = 1)
$criteria = $this->getDbCriteria();
(I’ve named all my scopes with whereXXX as it helps distinguish them from non-scope functions on the model.)
Then in my controller:
$activeUsers = new CActiveDataProvider(User::model()->whereActive(1));
$inactiveUsers = new CActiveDataProvider(User::model()->whereActive(0));
This ends up applying both scopes to the model - and both CActiveDataProvider end up with the same data. (An empty record set.)
So how do I avoid this sort of late binding of my model’s CDbCriteria to the data provider?
Note that my actual scopes are much more complicated, and I often want the default scope to be applied to both queries…
Thanks for updating this thread with your solution! I just ran into the same issue, and am wondering if you’ve learned anything since this post. I’m trying to do something simple like your example above, and find it hard to believe that it will require extending CActiveRecord.
I didn’t ever revisit this, I’m using the solution I posted in my project. I bit of a pain to remember when the project updates but because it references private variables I couldn’t come up with a better method.
The solution I’ve found to work (which was recommended in the issue documented above) is to create two new instances of the model, then apply the scopes to those…this way, they are treated independently. The problem seems to be that yii is caching the object, and reusing it, so the scope is not reset.
For this example, it should look something like this:
$activeUsers = new User();
$dpActiveUsers = new CActiveDataProvider($activeUsers->whereActive(1));
$inactiveUsers = new User();
$dpInactiveUsers = new CActiveDataProvider($inactiveUsers->whereActive(0));
This workaround seems similar in nature to what Woil came up with from the start, so good job