创建一个自定义客户端的校验器
在自定义校验器小节中,我们创建了一个独立的校验器。在本小节中,我们将会修改一个校验器来创建额外的客户端校验,它也会检查单词的数量。
准备
按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的应用。
如何做…
- 创建
@app/components/WordsValidator.php
:
<?php
namespace 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 <<<JS
if (value.split(/\w+/gi).length > $this->size ) {
messages.push("$message");
}
JS;
}
}
- 创建
@app/models/Article.php
:
<?php
namespace 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
:
<?php
namespace 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
:
<?php
use 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
校验器:
<?php
namespace 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 <<<JS
deferred.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
];
}
参考
欲了解更多信息,参考如下地址: