Yii2的表单验证:Ajax验证 [ 技术分享 ]

Yii2具有强大的表单验证功能,能用好表单验证,用户输入就基本掌握了,在这里我和各位聊聊Yii2的Ajax验证器。

实际上,Yii2并没有Ajax验证器这个概念,只是为了便于描述使用Ajax方式进行的数据验证,我在这里单独提出的一个说法而已!

所谓的Ajax验证器,就是当enableAjaxValidation==true时在request->isAjax代码块中执行的验证器。

Ajax验证代码结构大概是这样:

if (Yii::KaTeX parse error: Expected '}', got 'EOF' at end of input: …sAjax) { Yii::app->response->format = \yii\web\Response::FORMAT_JSON;
KaTeX parse error: Expected 'EOF', got '\yii' at position 10: result = \̲y̲i̲i̲\bootstrap\Acti…model);
return KaTeX parse error: Expected 'EOF', got '}' at position 9: result; }̲ 这段代码通常存在于服务器端验…model->validate())之前,请参考后面的源码。

Ajax验证实际上就是由客户端触发,使用Ajax技术进行的服务器端验证,验证结果以客户端页面的局部刷新的方式展现出来,因Ajax验证良好的用户体验而被广泛使用。

先来看看Ajax验证是什么样的效果?

31.jpg 上图红框中就是Ajax验证的结果,在国家名称中输入了“France”,在其失去焦点(鼠标在页面空白的地方点击一下)后,输入框变为了红色,其下方也出现了错误提示信息。需要注意的是:这个错误提示信息是由服务器端验证后发送过来的动态结果,这与客户端验证器是不同的。 从上图右边的表格你也可以看到“France”这个国家在数据库中是已经存在的!

32.jpg 上图中在国家名称中输入了“Egypt”,在其失去焦点后,输入框变为了绿色,即Ajax验证通过。

Ajax验证器的定义
类似的,Ajax验证器与服务器端验证器、客户端验证器定义方式都是一样的——在rules()中定义:

public function rules() {
return [
[[‘countryName’,‘countryAbbr’,‘continent’], ‘required’],
[‘continent’,‘default’,‘value’=>‘Asia’],
//Ajax验证器,对’countryName’进行唯一性(unique)检测
[[‘countryName’], ‘unique’,
//Ajax验证要使用的AR(Active Record)类
‘targetClass’ => ‘\frontend\models\Country’,
//Ajax验证时,'countryName’输入项对应于’name’字段进行验证(即对Country表中的’name’字段进行查询)
‘targetAttribute’ => [‘countryName’=>‘name’]
],
[[‘countryAbbr’], ‘unique’,‘targetClass’ => ‘\frontend\models\Country’, ‘targetAttribute’ => [‘countryAbbr’=>‘code’]],
];
}
要使上例代码中countryName验证规则成为真正的Ajax验证器,还需要在视图文件中对enableAjaxValidation进行设置。

在视图文件中对enableAjaxValidation进行设置有两个可选位置: 1、在ActiveField中对单项field进行设置 2、在ActiveForm中对整个表单进行设置 在此推荐第1种方法,即哪个表单项field需要Ajax验证时,就将它的enableAjaxValidation设置为true,这样避免触发不必要的Ajax请求,示例代码如下:

<?=$form->field($model,'countryName',['enableAjaxValidation'=>true])->textInput()?>

在Yii2中,ActiveForm的enableAjaxValidation默认值是false,即整个表单的Ajax验证失效,但此时是可以针对field开启单项的Ajax验证的。

if (Yii::KaTeX parse error: Expected '}', got 'EOF' at end of input: …sAjax) { Yii::app->response->format = \yii\web\Response::FORMAT_JSON;
KaTeX parse error: Expected 'EOF', got '\yii' at position 10: result = \̲y̲i̲i̲\bootstrap\Acti…model);
return KaTeX parse error: Expected 'EOF', got '}' at position 9: result; }̲ 最后就是在Controlle…model->validate()之前(请参考后面的源码),你的Ajax验证器就正式生效了!

本文所涉及到的程序源码:

文件位置:D:\phpwork\advanced\frontend\controllers\DemoController.php

<?php namespace frontend\controllers; use Yii; class DemoController extends CommonController{ public function actionForm3() { $model=new \frontend\models\Form3(); if ($model->load(Yii::$app->request->post())) { //是Ajax请求时才执行验证 if (Yii::$app->request->isAjax) { //使用ActiveForm的validate()方法对$model的数据进行验证 $result=\yii\bootstrap\ActiveForm::validate($model); Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;//设置返回客户端的结果使用json格式 //将验证结果返回客户端 return $result; } if($model->validate()){ if ($model->save()) { return $this->render('form3a',['model'=>$model]); }else{ return $this->error('Sorry,Data save fail!'); } }else{ return $this->errorDisplay($model->getErrors()); } }else{ $countries=\frontend\models\Country::find()->asArray()->all(); return $this->render('form3',['model'=>$model,'countries'=>$countries]); } } } 其中errorDisplay()方法是调用自CommonController,请参见: http://www.yiichina.com/topic/6736 文件位置:D:\phpwork\advanced\frontend\models\Form3.php <?php namespace frontend\models; use Yii; class Form3 extends \yii\base\Model{ public $countryName,$countryAbbr,$continent; public function attributeLabels() { return [ 'countryName'=>'国家名称', 'countryAbbr'=>'简称', 'continent'=>'大洲', ]; } public function rules() { return [ [['countryName','countryAbbr','continent'], 'trim'], [['countryName','countryAbbr','continent'], 'required'], ['continent','default','value'=>'Asia'], //Ajax验证器,对'countryName'进行唯一性(unique)检测 [['countryName'], 'unique', //Ajax验证要使用的AR(Active Record)类 'targetClass' => '\frontend\models\Country', //Ajax验证时,'countryName'输入项对应于'name'字段进行验证(即对Country表中的'name'字段进行查询) 'targetAttribute' => ['countryName'=>'name'] ], [['countryAbbr'], 'unique','targetClass' => '\frontend\models\Country', 'targetAttribute' => ['countryAbbr'=>'code']], ]; } public function save() { return true; } } 文件位置:D:\phpwork\advanced\frontend\views\demo\form3.php <?php use yii\bootstrap\ActiveForm; use yii\helpers\Html; ?>
<div class="panel panel-warning">
    <div class="panel-heading">
        <div class="panel-title">
            三、Yii2的表单验证——Ajax验证的验证器
        </div>
    </div>
    <div class="panel-body">
        <div class="row">
            <div class="col-md-7">
                <?php
                $form = ActiveForm::begin([

// ‘enableClientValidation’ => false,
‘enableClientValidation’ => true,
// ‘enableAjaxValidation’=>true,//从性能考虑,避免将整个表单设置为Ajax验证
‘enableAjaxValidation’=>false,//ActiveForm默认此值即为false,即整个表单的Ajax验证失效
‘layout’ => ‘horizontal’,
]);
?>

<?=$form->field($model,'countryName',['enableAjaxValidation'=>true])->textInput()?>

<?=$form->field($model,'countryAbbr',['enableAjaxValidation'=>true])->textInput()?>
<?=$form->field($model,'continent')->textInput()?>


<?= Html::submitButton('提     交 ', ['class' => 'btn btn-primary form-control']) ?>
<?= Html::resetButton('重     置 ', ['class' => 'btn btn-default form-control'])?>

<?php ActiveForm::end(); ?>









<?php
foreach ($countries as k=&gt;k=&gt;k=>item) {
echo ‘’;
}
?>
序号 国家 简称 大洲
’.(k+1).&lt;/TD&gt;&lt;TD&gt;.k+1).&#x27;&lt;/TD&gt;&lt;TD&gt;&#x27;.k+1).′</TD><TD>′.item[‘name’].’ ’.item[code].&lt;/TD&gt;&lt;TD&gt;.item[&#x27;code&#x27;].&#x27;&lt;/TD&gt;&lt;TD&gt;&#x27;.item[′code′].′</TD><TD>′.item[‘continent’].’





文件位置:D:\phpwork\advanced\frontend\views\demo\form3a.php

<?php use yii\widgets\DetailView; ?>
<div class="panel panel-warning">
    <div class="panel-heading">
        <div class="panel-title">
            三、Yii2的表单验证——Ajax验证的验证器(提交数据的显示)
        </div>
    </div>
    <div class="panel-body" style="height:500px;">
        <?php
        echo DetailView::widget([
            'model' => $model,
            'attributes' => [
                'countryName',
                'countryAbbr',
                'continent',
            ],
            'template' => '<tr><th class="text-right" style="width:150px;">{label}</th><td>{value}</td></tr>',
        ]);
        ?>
        <button onclick="history.back()" class="btn btn-default">返 回</button>
    </div>
</div>

Country类是Yii2官网实例中的一个类,请参照官网文档自行构建。 本例涉及的数据库表country,比官网实例中多了一个字段:continent,手动加上亦可:

CREATE TABLE country (
code CHAR(2) NOT NULL PRIMARY KEY,
name CHAR(52) NOT NULL,
continent CHAR(52) NOT NULL,
population INT(11) NOT NULL DEFAULT ‘0’
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO country VALUES (‘AU’,‘Australia’,24016400,‘Oceania’);
INSERT INTO country VALUES (‘BR’,‘Brazil’,205722000,‘South America’);
INSERT INTO country VALUES (‘CA’,‘Canada’,35985751,‘North America’);
INSERT INTO country VALUES (‘CN’,‘China’,1375210000,‘Asia’);
INSERT INTO country VALUES (‘DE’,‘Germany’,81459000,‘Europe’);
INSERT INTO country VALUES (‘FR’,‘France’,64513242,‘Europe’);
INSERT INTO country VALUES (‘GB’,‘United Kingdom’,65097000,‘Europe’);
INSERT INTO country VALUES (‘IN’,‘India’,1285400000,‘Asia’);
INSERT INTO country VALUES (‘RU’,‘Russia’,146519759,‘Europe’);
INSERT INTO country VALUES (‘US’,‘United States’,322976000,‘North America’);

上一篇:python--基础知识点梳理(二)


下一篇:将PHP页面显示为图像