Why CUniqueValidator changes the current model after validation fails?

In the [font="Courier New"]User[/font] model, there is a rule

array('username', 'unique')

If I try to create a new user who username (e.g., ‘admin’) has already been taken, validation will fail. But then, the model instance will change to that one which I tried to inserted (model with username ‘admin’ in this example).

Here is the view file that can reproduce this:

<h1>Update User: <?php echo $model->username; ?></h1>

<?php $form = $this->beginWidget('CActiveForm', array('id' => 'user-form')); ?>

   <?php echo $form->labelEx($model, 'username'); ?>

   <?php echo $form->textField($model, 'username'); ?>

   <?php echo $form->error($model, 'username'); ?>

   <?php echo Html::submitButton(‘Save'); ?>

<?php $this->endWidget(); ?>

Note that this view file prints [font=“Courier New”]$model->username[/font]. When I try to rename user ‘John’ to ‘admin’ and ‘admin’ already exists, validation falis and, [font=“Courier New”]$model->username[/font] changes to ‘admin’ instead of keeping at ‘John’!

This is normal.

Usually in the update action you have:

$model=$this->loadModel(); // in the model there is John, loaded from database

$model->attributes=$_POST['model']; // in the model there is admin, inserted by the user

$model->validate(); // or save: validation fails, nothing is touched

So in the model simply remains the value the user inserted. This is normal, because the user is informed that admin is already taken (not John, as should look if the validator were restoring the original).

Of corse no modification are done in the database (and, in this case, is impossible to save if you have a unique index!!)

when you assign the username admin - then the model contains the attribute username with the value admin… just look what your code is doing…

Ahh, I see the reason now. But there is one problem of this, if there are other fields (e.g., firstname, lastname) in the same form, if validation fails, they will be populated with values from the model instance that I tried to insert (firstname and lastname of user ‘admin’ in this example)! So what’s the best way to deal with this? Thanks in advance.

The best way is what CRUD generates by default:

It keeps all data user inserted (so he is not requested to insert another time)

It put in evidence fields where there are mistake, on order to help the user to correct (if it were reloading from db, how can the user correct himself if he doesn’t know how he mistook)?

It is saving ONLY if all data are corrected.