Why? Most of the time, the AR state is completely irrelevant - most validations do not depend on the state of AR at all. And as a workaround, you propose this statement:
$model->scenario='being '.($model->isNewRecord ? 'inserted':'updated').' by an administrator'
Look at the complexity of this statement - think of how many times you would need to write that same statement over again, and think about what it expresses: “we don’t care about AR state in this case”. That is probably the case for most validation rules.
I think the most common situation should require the most simple expression - but this achieves the opposite.
But who says you only need to validate once?
And how can you explain this clearly in documentation? "If you need to use the scenario for other aspects, besides validation as provided by the framework, please track your own scenarios using some other variable".
Even if you could explain it like this (or better), that just raises more questions - if I’m tracking my scenario using a different variable, how can I add validation rules that apply to my scenario?
And even if you end up writing your own validator, perhaps extending a standard validator, to take your scenario into account, you would still run into edge cases, for example when validation is performed more than once, where your scenario is out of sync with $scenario - something that passed validation the first time might not pass the second time, and not because the scenario changed, but because the condition of AR changed internally, something your application has no control of.
But read it again:
"Scenario affects how validation is performed and which attributes can be massively assigned"
How can the circumstances of AR’s internal statemachine management be described as what is performed and what can be done to a model?
Remember, this an attribute that applies to any model, not just to persistent ones - but you think it’s acceptable that, under some condition, in this case inserting, the meaning of this property suddenly changes to describe something that is unrelated to models in general, and specific to AR?
I disagree. You have this one case, inserting, where suddenly the meaning of an attribute changes - I think that’s messy, confusing, and hard to explain… in my opinion, anything that’s too hard to explain, or contains too many “what if’s”, just isn’t good enough.
I hope you don’t think I’m just trying to be argumentative here
I think there’s a real general issue here, and the current approach is not clean and causes edge cases.
Citing Ruby on Rails, it completely separates the condition of the associated database record from anything else - the “on” attribute, for validations, is used only to track the condition of the underlying record, e.g. “update” or “insert”, nothing else, thus avoiding the domain overlap that occurs in Yii’s AR.
To describe scenarios or cases where a particular rule may or may not apply, Rails uses another attribute named "if", and you can see an example of how that works here.
An example of how that might translate to Yii’s AR could be something along the lines of this:
class User extends CModel
{
public $registering=false;
public function rules()
{
return array(
array('username', 'required'),
array('username', 'length', 'min'=>3, 'max'=>12),
array('password', 'compare', 'compareAttribute'=>'password2', 'if'=>'registering'),
array('password', 'authenticate', 'if'=>'loggingIn'),
);
}
public function getLoggingIn()
{
return isset($_POST['LoginForm']) ? true : false;
}
}
...
class UserController extends CController
{
public function actionRegister()
{
$user = new User;
$user->registering = true;
if (isset($_POST['User']))
{
$user->attributes = $_POST['User'];
if ($user->validate())
{
// etc.
}
}
}
}
It would seem that maybe what we need is an untanglement of this domain overlap, but in the opposite direction?
Maybe the answer is not to add a separate property, e.g. $condition, for exclusive use by AR, but rather to reserve the existing $scenario for exclusive use by AR?
I guess the problem with that idea, is that $scenario is already present in the general-purpose CModel - there is probably already myriad code using the $scenario attribute for conditional validation of form models, for example.
I don’t have an answer to that right now, but let’s try to think in another direction and see where that takes us. Ideas, anyone?