Revision #5 has been created by le_top on Aug 12, 2014, 6:15:24 AM with the memo:
Typo corrections + titles added + some rewrites
« previous (#4)
Changes
Title
unchanged
Using updateAll and deleteAll with scopes
Category
unchanged
How-tos
Yii version
unchanged
Tags
unchanged
updateAll, deleteAll, scopes, conditions
Content
changed
This article is about how to use Using _CActiveRecord->updateAll()_ and _CActiveRecord->deleteAll()_ with scopes and criteria
almost like you are used to with _findAll()_ , _find()_ and the other retrieval methods.
Those amongst you thatrequires some _tricks_ that are explained in this article. While _findAll()_ , _find()_ and some other methods use scopes automatically, _updateAll()_ and _deleteAll()_ do not.
The limitation of _updateAll()_ and _deleteAll()_
--------------------------------------------------
If you tried,
you will know that
while these functions allow you to specify a $condition as a parameter, but that they do not use the conditions and scopes that you may have defined on the model().
In other words, the next code does not behave as you might expect:[...]
This behavior is by design and has been subject to discussions on the forum, etc.
The solution
------------
Fortunately, there is a way to use the wonderful feature to define scopes and conditions in a high level manner.
The trick is to extract the criteria by using _applyScopes()_. The issue is that _applyScope
s()_ will suppose an alias 't' for the table. And that breaks the SQL query as the
_updateAll()
_ and
_deleteAll()
_ methods do not apply an alias to the table you are updating to or deleting from. They just keep their original name.
Therefore, the extra trick is to set the alias to the table's name before applying the scope.[...]
$criteria=new CDbCriteria();
Alert::model()->alert_id($alert_id)->is_ack(1)->forEntity($this->trackerId)->web()->applyScopes($criteria);
Alert::model()->updateAll(array('is_ack'=>10),$criteria);
```
So the above code first sets the alias to use with the criteria. It then sets the $criteria. And finally it calls _updateAll()_ to update all the selected records.
Making the solution more robust
-------------------------------
Now that is great, and most developers would stop there. However, the remaining issue with that is that you have to think about using _applyScopes()_ and setting the alias every time. And if you forget it by accident, all your records will be updated with _updateAll()_ (without taking the scopes into account) and you might just break the contents of your database.[...]
And what is more is that if you forget to assign the alias, you will get an exception !
Automating
----------
So, as promised, in order to help you update your Gii basemodel, here is the extract of what I put in my basemodel for Gii (I use Awe/AweModel).
```php
/**[...]