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=>item) {
echo ‘’;
}
?>
序号 | 国家 | 简称 | 大洲 |
’.(k+1).′</TD><TD>′.item[‘name’].’ | ’.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’);