在 Yii2 中使用带有 ActiveForm 的自定义验证器
Using custom validators with ActiveForm in Yii2
我想制作像内置验证一样的自定义验证功能required
。我这里有示例代码:
型号:
use yii\base\Model;
class TestForm extends Model
{
public $age;
public function rules(){
return [
['age', 'my_validation']
];
}
public function my_validation(){
//some code here
}
}
查看:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
$this->title = 'test';
?>
<div style="margin-top: 30px;">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'age')->label("age") ?>
<div class="form-group">
<?= Html::submitButton('submit', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
控制器:
use app\models\form\TestForm;
use yii\web\Controller;
class TestController extends Controller
{
public function actionIndex(){
$model = new TestForm();
if($model->load(\Yii::$app->request->post())){
return $this->render('test', array(
'model'=>$model,
'message'=>'success'
));
}
return $this->render('test', array('model'=>$model));
}
}
在这个例子中,我有一个年龄字段,这个 my_validation
函数应该在提交之前检查年龄是否超过 18 岁,如果年龄低于 18 岁则抛出错误。这个验证应该由 ajax 就像在 required
规则的情况下,如果您尝试提交空字段。
尽管您也可以在您的场景中使用 Conditional Validators
when
和 whenClient
但是我建议使用更复杂的方法来定义自定义验证器,因为根据文档
To create a validator that supports client-side validation, you should
implement the yii\validators\Validator::clientValidateAttribute()
method which returns a piece of JavaScript code that performs the
validation on the client-side. Within the JavaScript code, you may use
the following predefined variables:
attribute:
the name of the attribute being validated.
value:
the value being validated.
messages:
an array used to hold the validation error messages for the attribute.
deferred:
an array which deferred objects can be pushed into (explained in the next subsection).
所以您需要做的是创建一个验证器并将其添加到您想要的字段的规则中。
您需要小心复制以下代码如果您没有提供实际型号名称并相应地更新字段名称。
1) 首先要做的是将 ActiveForm
小部件更新为以下
$form = ActiveForm::begin([
'id' => 'my-form',
'enableClientValidation' => true,
'validateOnSubmit' => true,
]);
2) 将您的模型 rules()
函数更改为以下
public function rules()
{
return [
[['age'], 'required'],
[['age'], \app\components\AgeValidator::className(), 'skipOnEmpty' => false, 'skipOnError' => false],
];
}
3) 从您的模型中删除自定义验证函数 my_validation()
我希望您检查其中的年龄限制 18+
我们将移动该逻辑进入验证器。
现在在 components
目录中创建一个文件 AgeValidator.php
,如果您使用 basic-app
,请在项目的根目录中添加文件夹 components
(如果有的话)不存在新建一个,把下面的代码复制进去
但是
我假定了您上面提供的模型名称,因此如果它不是实际名称,您必须更新 clientValidateAttribute
函数中 javascript
语句中的字段名称,您会看到在下面的验证器中,因为 ActiveForm
中字段的 id
属性是以 #modelname-fieldname
格式生成的(所有小写)所以根据上面给定的模型,它将是 #testform-age
相应地更新它,否则验证将不起作用。如果您打算将命名空间保存在其他地方,请务必在下面的验证器和模型 rules()
中更新命名空间。
<?php
namespace app\components;
use yii\validators\Validator;
class AgeValidator extends Validator
{
public function init()
{
parent::init();
$this->message = 'You need to be above the required age 18+';
}
public function validateAttribute($model, $attribute)
{
if ($model->$attribute < 18) {
$model->addError($attribute, $this->message);
}
}
public function clientValidateAttribute($model, $attribute, $view)
{
$message = json_encode($this->message, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return <<<JS
if (parseInt($("#testform-age").val())<18) {
messages.push($message);
}
JS;
}
}
我想制作像内置验证一样的自定义验证功能required
。我这里有示例代码:
型号:
use yii\base\Model;
class TestForm extends Model
{
public $age;
public function rules(){
return [
['age', 'my_validation']
];
}
public function my_validation(){
//some code here
}
}
查看:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
$this->title = 'test';
?>
<div style="margin-top: 30px;">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'age')->label("age") ?>
<div class="form-group">
<?= Html::submitButton('submit', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
控制器:
use app\models\form\TestForm;
use yii\web\Controller;
class TestController extends Controller
{
public function actionIndex(){
$model = new TestForm();
if($model->load(\Yii::$app->request->post())){
return $this->render('test', array(
'model'=>$model,
'message'=>'success'
));
}
return $this->render('test', array('model'=>$model));
}
}
在这个例子中,我有一个年龄字段,这个 my_validation
函数应该在提交之前检查年龄是否超过 18 岁,如果年龄低于 18 岁则抛出错误。这个验证应该由 ajax 就像在 required
规则的情况下,如果您尝试提交空字段。
尽管您也可以在您的场景中使用 Conditional Validators
when
和 whenClient
但是我建议使用更复杂的方法来定义自定义验证器,因为根据文档
To create a validator that supports client-side validation, you should implement the
yii\validators\Validator::clientValidateAttribute()
method which returns a piece of JavaScript code that performs the validation on the client-side. Within the JavaScript code, you may use the following predefined variables:
attribute:
the name of the attribute being validated.
value:
the value being validated.
messages:
an array used to hold the validation error messages for the attribute.
deferred:
an array which deferred objects can be pushed into (explained in the next subsection).
所以您需要做的是创建一个验证器并将其添加到您想要的字段的规则中。
您需要小心复制以下代码如果您没有提供实际型号名称并相应地更新字段名称。
1) 首先要做的是将 ActiveForm
小部件更新为以下
$form = ActiveForm::begin([
'id' => 'my-form',
'enableClientValidation' => true,
'validateOnSubmit' => true,
]);
2) 将您的模型 rules()
函数更改为以下
public function rules()
{
return [
[['age'], 'required'],
[['age'], \app\components\AgeValidator::className(), 'skipOnEmpty' => false, 'skipOnError' => false],
];
}
3) 从您的模型中删除自定义验证函数 my_validation()
我希望您检查其中的年龄限制 18+
我们将移动该逻辑进入验证器。
现在在 components
目录中创建一个文件 AgeValidator.php
,如果您使用 basic-app
,请在项目的根目录中添加文件夹 components
(如果有的话)不存在新建一个,把下面的代码复制进去
但是
我假定了您上面提供的模型名称,因此如果它不是实际名称,您必须更新 clientValidateAttribute
函数中 javascript
语句中的字段名称,您会看到在下面的验证器中,因为 ActiveForm
中字段的 id
属性是以 #modelname-fieldname
格式生成的(所有小写)所以根据上面给定的模型,它将是 #testform-age
相应地更新它,否则验证将不起作用。如果您打算将命名空间保存在其他地方,请务必在下面的验证器和模型 rules()
中更新命名空间。
<?php
namespace app\components;
use yii\validators\Validator;
class AgeValidator extends Validator
{
public function init()
{
parent::init();
$this->message = 'You need to be above the required age 18+';
}
public function validateAttribute($model, $attribute)
{
if ($model->$attribute < 18) {
$model->addError($attribute, $this->message);
}
}
public function clientValidateAttribute($model, $attribute, $view)
{
$message = json_encode($this->message, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return <<<JS
if (parseInt($("#testform-age").val())<18) {
messages.push($message);
}
JS;
}
}