Yii provides a good set of built-in form validators that cover the most typical of developer's needs and are highly configurable. However, in some cases, the developer may face a need to create a custom validator.
A good example would be the website ownership validation. For a few of their services, Google requires you to upload a file with the name and content specified to your website, and then checks if it is there. We will do the same.
There are two ways to achieve it; you can use a class method as a validator, or the second way is to create a separate class.
protected/models/SiteConfirmation.php
as follows:<?php class SiteConfirmation extends CFormModel { public $url; public function rules() { return array( array('url', 'confirm'), ); } public function confirm($attribute,$params) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $this->url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); curl_close($ch); if(trim($output)!='code here') $this->addError('url','Please upload file first.'), } }
protected/controllers/TestController.php
as follows:<?php class TestController extends CController { function actionIndex() { $confirmation = new SiteConfirmation(); $confirmation->url = 'http://yiicookbook.org/verify.html'; if($confirmation->validate()) echo 'OK'; else echo 'Please upload a file.'; } }
In the SiteConfirmation
model, we define a $url
field and add a rules
method that defines a single validation rule for this field. As there is no built-in validator named confirm
, Yii assumes that we want to describe the validation rule in a method named confirm
. In this method we use PHP's standard CURL to get the verify.html
file's contents from a remote host and compare its content with the code here
string. If the file content is different, then we add an error using the addError
method.
Optionally, we can use two validation method arguments: $attribute
and $params
. For example, we can specify the validation rule in the following way:
array('url', 'confirm', 'param1' => 'value1', 'param2' => 'value3'),
We then get the $attribute
value set to url
and the $params
value set to the following:
array ( 'param1' => 'value1' 'param2' => 'value3' )
As we probably want to reuse this kind of validator, we will move its functionality from a model method to a separate class. So, create a file named protected/components/RemoteFileValidator.php
as follows:
<?php class RemoteFileValidator extends CValidator { public $content = ''; protected function validateAttribute($object,$attribute) { $value=$object->$attribute; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $value); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); curl_close($ch); if(trim($output)!=$this->content) $this->addError($object,$attribute,'Please upload file first.'), } }
The custom validator class should extend CValidator
and implement its abstract validateAttribute
method. Arguments passed on to it are $object
, which is an instance of the validated model, and $attribute
, which contains the validated attribute name. Parameters that are passed are assigned to corresponding public properties of the validator class.
That is it. Now, we will use it. In the SiteConfirmation
model, we should change the validation rule to the following:
array('url', 'RemoteFileValidator', 'content' => 'code here'),
Here we have used an external validator name. If there is no method with the same name in the model and no built-in validator with same name, Yii will try to find an external validator class with the name or path alias specified.
The rest of the code stays untouched and now you can reuse the validator in other models.
For further information, refer to the following URLs:
3.138.179.119