Good day. Today I would like to make out such an interesting feature of the Yii Framework as the validation of these models. At the time of this writing, the current version of the framework is
1.1.10 , and we’ll actually consider validation on it.
I want to say right away that I don’t want to reprint manuals and APIs, so I will refer to ready sources whenever possible. In addition, I will not describe how to use validators. I will try to reveal the mechanism of validation of Yii models based on validation rules, so that using them you understand what is actually happening and where, if anything happens, you can look for errors.
Beginning of understanding validators
So, on the wonderful site
yiiframewrok.ru there is a recipe section.
This section has a
Quick Reference to validation . The original of this article is located at
this address .
After reading this article you will understand:
- How to set validation rules
- What is a specific rule?
- Learn the list of standard validators and their parameters
Next is to read the article
Creating a Model (
Original ) from which you will learn:
- Something about the scenarios. (I want to emphasize this point, it is poorly documented)
- How to create validators
- How to perform validation
By the way, examples of creating your validators are well described in the book:
Yii 1.1 Application Development CookbookArmed with the knowledge gained, we can go ahead and figure out what happens when we call:
CModel::validate();
Depth CModel :: validate ();
CModel::validate($attributes=null, $clearErrors=true);
method
CModel::validate($attributes=null, $clearErrors=true);
- takes as input 2 optional parameters (a list of attributes for valdation, and the clearErrors key, which clears the array with errors before calling validators)
This is important to understand if you will extend the standard Yii models and use the
CModel::addError();
method
CModel::addError();
for their own purposes, because
CModel::validate();
returns true in case of successful data validation and false if
CModel::hasErrors();
returns true.
In addition, it should be noted here that vadilation will not work if you override the
CModel::beforeValidate();
method
CModel::beforeValidate();
and it returned false.
In order to dilute the text, let's take a look at the code and everything will become more or less clear:
- public function validate ( $ attributes = null , $ clearErrors = true )
- {
- if ( $ clearErrors )
- $ this -> clearErrors ( ) ;
- if ( $ this -> beforeValidate ( ) )
- {
- foreach ( $ this -> getValidators ( ) as $ validator )
- $ validator -> validate ( $ this , $ attributes ) ;
- $ this -> afterValidate ( ) ;
- return ! $ this -> hasErrors ( ) ;
- }
- else
- return false ;
- }
I think that there are no more questions here, so let's take a look at the
CModel::getValidator()
method
CModel::getValidator()
foreach ( $ this -> getValidators ( ) as $ validator )
to understand how Yii gets a list of validators based on the rules specified in the
CModel::rules()
method
')
CModel :: getValidators ()
- public function getValidators ( $ attribute = null )
- {
- if ( $ this -> _validators === null )
- $ this -> _validators = $ this -> createValidators ( ) ;
- $ validators = array ( ) ;
- $ scenario = $ this -> getScenario ( ) ;
- foreach ( $ this -> _validators as $ validator )
- {
- if ( $ validator -> applyTo ( $ scenario ) ) {
- if ( $ attribute === null || in_array ( $ attribute , $ validator -> attributes , true ) )
- $ validators [ ] = $ validator ;
- }
- }
- return $ validators ;
- }
The method returns an array of validators described by the rules in the model.
An interesting point here begins with the 7th row. I mentioned scripts above. So, here we see that the validator is added to the chain, only if the
CValidator::applyTo($scenario);
method
CValidator::applyTo($scenario);
returns true, and it returns true either in the case when the
“on” parameter is not specified or in the case when the validator refers to the scenario in which the model is executed.
Go ahead. Consider the
CModel:createValidators();
method
CModel:createValidators();
$ this -> _validators = $ this -> createValidators ( ) ;
which in essence will be the lower and last level of parsing validation rules, and then we will summarize some results.
Closer to completion: CModel :: createValidators ()
- public function createValidators ( )
- {
- $ validators = new CList ;
- foreach ( $ this -> rules ( ) as $ rule )
- {
- if ( isset ( $ rule [ 0 ] , $ rule [ 1 ] ) ) // attributes, validator name
- $ validators -> add ( CValidator :: createValidator ( $ rule [ 1 ] , $ this , $ rule [ 0 ] , array_slice ( $ rule , 2 ) ) ) ;
- else
- throw new CException ( Yii :: t ( 'yii' , '{class} has an invalid validation rule. and the array's name.' , array ( '{class}' => get_class ( $ this ) ) ) ) ;
- }
- return $ validators ;
- }
So we got to the bottom level. This method performs the same validation rules described in
CModel::rules()
and using the static method of the class
CValidator::createValidator()
creates objects of validators described by these rules.
CValidator::createValidator()
method
API and also recalling the standard parameters of the validation rule
- array (
- 'model field list' ,
- 'validator' ,
- 'on' => 'script name' ,
- 'message' => 'error message' ,
- ... validation parameters ...
- ) ;
, everything will immediately fall into place.
Let's sum up
As you can see, the algorithm for parsing validation rules is not such a complicated thing. The main thing is to have a desire to understand and understand the problem. Understanding how the code works eliminates a lot of various questions arising during development, when something goes wrong and the program is not executed as it should.
In conclusion, we can summarize some features that will allow us to understand why your validator may not work as it would like, or why some validation rule is not executed.
- When you call the
CModel::validate()
method, it checks whether the CModel::beforeValidate()
method is CModel::beforeValidate()
.
If the method is not validated, it is considered as not passed. - If the
CModel::hasErrors()
method returns true, the validation is considered as not passed - When calling the
CModel::getValidators()
method, only validators are added that relate to the current script as well as validators for which the script does not specify the validation rules