创建一个自定义客户端的校验器
在自定义校验器小节中,我们创建了一个独立的校验器。在本小节中,我们将会修改一个校验器来创建额外的客户端校验,它也会检查单词的数量。
准备
按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的应用。
如何做…
- 创建
@app/components/WordsValidator.php:
<?phpnamespace app\components;use yii\validators\Validator;class WordsValidator extends Validator{public $size = 50;public $message = 'The number of words must be less than {size}';public function validateValue($value){preg_match_all('/(\w+)/i', $value, $matches);if (count($matches[0]) > $this->size) {return [$this->message, ['size' => $this->size]];}}public function clientValidateAttribute($model, $attribute, $view){$message = strtr($this->message, ['{size}' => $this->size]);return <<<JSif (value.split(/\w+/gi).length > $this->size ) {messages.push("$message");}JS;}}
- 创建
@app/models/Article.php:
<?phpnamespace app\models;use app\components\WordsValidator;use yii\base\Model;class Article extends Model{public $title;public function rules(){return [['title', 'string'],['title', WordsValidator::className(), 'size' => 10],];}}
- 创建
@app/controllers/ValidationController.php:
<?phpnamespace app\controllers;use app\models\Article;use Yii;use yii\web\Controller;class ValidationController extends Controller{public function actionIndex(){$model = new Article();if ($model->load(Yii::$app->request->post()) &&$model->validate()) {Yii::$app->session->setFlash('success', 'Model is valid');}return $this->render('index', ['model' => $model,]);}}
- 创建
@app/views/validation/index.php:
<?phpuse yii\bootstrap\ActiveForm;use yii\helpers\Html;?><h1>Article form</h1><?php if (Yii::$app->session->hasFlash('success')): ?><div class="alert alert-success"><?= Yii::$app->session->getFlash('success'); ?></div><?php endif; ?><?php $form = ActiveForm::begin(); ?><?= $form->field($model, 'title') ?><div class="form-group"><?= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?></div><?php ActiveForm::end(); ?>
工作原理…
打开index.php?r=validation运行校验控制器。如果你输入了超过10个单词,你将会看到一个错误:

如果输入的少于10个单词,客户端校验是成功的:

首先,我们创建了@app/componets/WordsValidator.php,它继承了@yii\validators\Validator类,添加新创建的校验器到Article模型的标题属性:
..['title', WordsValidator::className(), 'size' => 10],..
在我们的校验器内部,我们已经定义了两个特殊的方法:validatorValue()和clientValidatorAttribute()。
我们的校验器类实现了validatorValue()方法来支持数据模型之外的数据校验。第二个方法只是返回客户端需要的JavaScript。
更多…
如果我们希望隐藏校验器实现,或者希望控制所有的校验过程在服务端,我们可以创建一个Deferred对象。
首先,修改WordsValidator校验器:
<?phpnamespace app\components;use yii\validators\Validator;use yii\helpers\Url;class WordsValidator extends Validator{public $size = 50;public $message = 'The number of words must be less than {size}';public function validateValue($value){if (str_word_count($value) > $this->size) {return ['The number of words must be less than {size}',['size' => $this->size]];}return false;}public function clientValidateAttribute($model, $attribute, $view){$url = Url::toRoute(['validation/check-words']);return <<<JSdeferred.push($.get("$url", {words:value}).done(function(data) {if (!data.result) {messages.push(data.error);}}));JS;}}
在先前的代码中,deferred变量由Yii提供,它是Deferred对象组成的一个数组,$.get()JQuery方法创建一个Deferred对象,它被放入了deferred数组中。
第二,添加checkWords动作到validation控制器中:
public function actionCheckWords(){\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;$value = Yii::$app->getRequest()->get('words');$validator = new WordsValidator(['size' => 10,]);$result = $validator->validate($value, $error);return ['result' => $result,'error' => $error];}
参考
欲了解更多信息,参考如下地址:
