Since Yii 1.1.x the declaration of safe attributes has changed (discussed here). Unfortunately i find the new way very tedious if you have many scenarios and multiple rules per attribute, which is rather often the case in my models. Let me show you why.
Take these example rules for a username:
-
must only contain specific characters
-
must be unique
-
must (for some reason) not be an existing email address
-
is required in some scenarios
And we could have different scenarios like login, register, invite, edit-profile, admin. Username should not be safe in all scenarios, only in login, register, invite and admin. To achieve this we need 3 rules and specify all of the 4 safe scenarios on each of them. This is really tedious:
array('username', 'match', 'pattern'=>'/[a-z]+/', 'on'=>'login,register,invite,admin'),
array('username', 'unique', 'on'=>'login,register,invite,admin'),
array('username', 'unique', 'attributeName'=>'email', 'on'=>'login,register,invite,admin');
array('username', 'required', 'on'=>'login,register,invite,admin'),
You see that most of this code is the same scenarios repeated again and again. Situation gets even worse with complex models with many attributes that should be used in different scenarios: We have to declare the safe scenarios with every rule.
Now i noticed that CValidator has the safe property and thought it might solve my problem. My expectation how this works was like this:
array('username', 'match', 'pattern'=>'/[a-z]+/', 'safe'=>false),
array('username', 'unique', 'safe'=>false),
array('username', 'unique', 'attributeName'=>'email', 'safe'=>false),
array('username', 'required', 'on'=>'login,register,invite,admin'),
Only the last rule is used to define, where an attribute is considered safe. Less to type and much cleaner. Also easier to add/remove scenarios. This resembles the 1.0.x behavior: Rules are separated from the declaration of safety. I would prefer this in some cases for the reasons described above. But this doesn’t work as expected. With this setup username is never safe!
To make a long story short:
It seems like safe=>false translates to: This attribute is not safe, no matter what other rules define.
I would prefer if it translates to: This attribute is not safe, unless there is another rule that has safe=>true (which is the default value for any rule).