Validation rules issues when using model's attribute as additional parameters #3001

Open
rsn86 opened this Issue Oct 30, 2013 · 5 comments

Projects

None yet

4 participants

@rsn86
rsn86 commented Oct 30, 2013

As CModel._validators = CModel.createValidators() is called before any model's attribute be setted, the validation rules are compiled with attributes's default values.
This could lead to validation issues. To avoid that, CModel.validate() should always compile validation rules on runtime.

This is best observable when using CUniqueValidato, e.g.:

class MyModel extends CFormModel {

    public $someAttr;
    public $uniqueAttr;

    public function rules() {
        return array(
            array('uniqueAttr', 'unique', 'className'=>'AnotherClass', 'allowEmpty'=>false, 'skipOnError'=>true, 'criteria'=>array('condition'=>"notNullAttr=:someAttr",'params'=>array(':someAttr'=>$this->someAttr))),
        );
    }

}

In this example, CModel._validators will contain a CUniqueValidator validation rule
with :someAttr setted as NULL. CModel.validate() will always return TRUE regardless of MyModel->uniqueAttr 's value, since there isn't any AnotherClass->notNullAttr == NULL.

@resurtm
resurtm commented Oct 30, 2013

Not an issue. This is by design. Treat rules() as a some sort of static method, it mustn't know anything about particular model instance. For your case consider making a new model method based validator.

@resurtm resurtm closed this Oct 30, 2013
@rsn86
rsn86 commented Oct 31, 2013

If this is the understanding about it at least it should be well documented.

Using protected attributes instead of private, or setter/getters for all vars, would allow a more flexible usage of the framework.

A resetValidators() { $this->_validators = null; } method would do the trick too.

All that need to be done is set CModel->_validators = null before validation.

@resurtm
resurtm commented Oct 31, 2013

If this is the understanding about it at least it should be well documented.

Maybe it worth documenting it.

The rules() method is generally declarative thing and it should stick with KISS. If you want to somehow deal with the particular validated object you have to create your own class based or method based validator.

All that need to be done is set CModel->_validators = null before validation.

The problem is that if we'll use this way lazy validators initiation would become meaningless.

@resurtm resurtm reopened this Oct 31, 2013
@resurtm resurtm was assigned Oct 31, 2013
@rsn86
rsn86 commented Oct 31, 2013

I guess a better solution would be to use evaluateExpression() on validator's parameters

@resurtm resurtm was unassigned by samdark Oct 23, 2014
@cebe cebe modified the milestone: 1.1.17, 1.1.16 Oct 24, 2014
@samdark samdark modified the milestone: 1.1.17, 1.1.18 Dec 29, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment