Yii2:ActiveForm:在一个字段上组合规则/多重验证 [英] Yii2: ActiveForm: combine rules / multiple validation on one field

查看:27
本文介绍了Yii2:ActiveForm:在一个字段上组合规则/多重验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

登录表单:

公共函数规则(){返回 [//用户名和密码都需要[['用户名', '密码'], '必填'],//用户名应该是一个数字和 8 位数字[['username'], 'number', 'message'=>'{attribute} 必须是数字'],[['用户名'], '字符串', '长度' =>8],//密码由validatePassword() 验证['密码','验证密码'],];}/*** 验证密码.* 此方法用作密码的内联验证.** @param string $attribute 当前正在验证的属性* @param array $params 规则中给出的附加名称-值对*/公共函数validatePassword($attribute, $params){如果 (!$this->hasErrors()) {$user = $this->getUser();if (!$user || !$user->validatePassword($this->password)) {$this->addError($attribute, '用户名或密码不正确.');}}}

我为上面看到的同一个字段设置了 2 条规则:

[['username'], 'number', 'message'=>'{attribute} 必须是数字'],[['用户名'], '字符串', '长度' =>8],

我希望表单针对以下 3 个场景情况显示不同的错误消息:

  1. 提供的值既不是数字,也不是 8 个字符(数字).
  2. 提供的值是一个数字,但不是 8 个字符(数字).
  3. 提供的值不是数字,而是 8 个字符(数字).

我的问题是 2 折:

A.有没有办法以任何标准,Yii2 方式组合这些规则.
B. 在我之前的问题中,我尝试设置自定义验证器(解决此问题的显而易见的方法),但它很简单地被忽略了.我可以使其验证的唯一方法是将 username 字段添加到场景中.但是,一旦我也添加了 password,它又被忽略了.你能想到的任何原因吗?编辑:skipOnError = false 在这种行为中没有任何改变.

所以请在回答时确保最好在 yii2/advanced 中进行测试;我几乎没有接触过默认设置,所以应该很容易测试.

EDIT:为清楚起见,我只想允许 8 个字符(数字)的数字,因此它们可能有一个前导 0,例如.0000000100000000 就此而言.这就是为什么它必须是一个数字字符串.

解决方案

针对不同情况组合规则和显示自定义错误消息的最佳方法是创建自定义验证器.现在,如果您也希望在客户端使用它(这是我在上面的问题 B 中详述的问题之一,感谢 @Beowulfenator 在这方面的领导),您必须创建一个实际的自定义验证器类扩展自 yii2 原生验证器类.

这是一个例子:

CustomValidator.php

<?php命名空间 app\components\validators;使用 Yii;使用 yii\validators\Validator;类 CustomValidator 扩展了 Validator{公共函数初始化(){父::init();}公共函数 validateAttribute($model, $attribute) {$model->addError($attribute, $attribute.' message');}公共函数 clientValidateAttribute($model, $attribute, $view){返回<<<JSmessages.push('$attribute message');JS;}}

登录表单.php

<?php命名空间 common\models;使用 Yii;使用 yii\base\Model;使用 app\components\validators\CustomValidator;/*** 登录表格*/类 LoginForm 扩展模型{公共 $ 用户名;公共 $password;公共 $custom;私人 $_user;/*** @inheritdoc*/公共函数规则(){返回 [//用户名和密码都需要[['用户名', '密码'], '必填'],//用户名应该是一个数字和 8 位数字[['username'], 'number', 'message'=>'{attribute} 必须是数字'],[['用户名'], '字符串', '长度' =>8],//密码由validatePassword() 验证['密码','验证密码'],['custom', CustomValidator::className()],];}//...

登录.php

<?php/* @var $this yii\web\View *//* @var $form yii\bootstrap\ActiveForm *//* @var $model \common\models\LoginForm */使用 yii\helpers\Html;使用 yii\bootstrap\ActiveForm;$this->title = '登录';?><div class="site-login text-center"><h1><?php echo Yii::$app->name;?></h1><?php $form = ActiveForm::begin(['id' =>'登录表格','fieldConfig' =>['模板' =>"{标签}\n{输入}"],'启用客户端验证' =>真的,'validateOnSubmit' =>真的,]);?><?= $form->errorSummary($model, ['header'=>'']) ?><div class="row"><div class="col-lg-4 col-lg-offset-4"><div class="col-lg-10 col-lg-offset-1"><div style="margin-top:40px"><?= $form->field($model, 'username') ?>

<div><?= $form->field($model, 'password')->passwordInput() ?>

<div><?= $form->field($model, 'custom') ?>

<div class="form-group" style="margin-top:40px"><?= Html::submitButton('Login', ['class' => 'btn btn-default', 'name' => 'login-button']) ?>

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

LoginForm:

public function rules()
{
    return [
        // username and password are both required
        [['username', 'password'], 'required'],
        // username should be a number and of 8 digits
        [['username'], 'number', 'message'=>'{attribute} must be a number'],
        [['username'], 'string', 'length' => 8],
        // password is validated by validatePassword()
        ['password', 'validatePassword'],
    ];
}

/**
 * Validates the password.
 * This method serves as the inline validation for password.
 *
 * @param string $attribute the attribute currently being validated
 * @param array $params the additional name-value pairs given in the rule
 */
public function validatePassword($attribute, $params)
{
    if (!$this->hasErrors()) {
        $user = $this->getUser();
        if (!$user || !$user->validatePassword($this->password)) {
            $this->addError($attribute, 'Incorrect username or password.');
        }
    }
}

I have set up 2 rules for the same field as you can see above:

[['username'], 'number', 'message'=>'{attribute} must be a number'],
[['username'], 'string', 'length' => 8],

I would like the form to display different error messages for the following 3 scenarios situations:

  1. The provided value is neither a number, nor 8 characters (digits).
  2. The provided value is a number, but is not of 8 characters (digits).
  3. The provided value is not a number, but is of 8 characters (digits).

My question is 2 fold:

A. Is there a way to combine these rules in any standard, Yii2 way.
B. In my previous question I have tried to set up a custom validator (the obvious way to solve this), but it was very simply ignored. The only way I could make it validate was if I added the username field to a scenario. However, once I added password too, it was again ignored. Any reason's for this that you can think of? EDIT: skipOnError = false changed nothing at all in this behaviour.

So please, when you answer, make sure you test it preferably in yii2/advanced; I barely touched the default set up, so it should be easy to test.

EDIT: for clarity, I would like to only allow numbers that are of 8 characters (digits), so they can potentially have a leading 0, eg. 00000001, or 00000000 for that matter. This is why it has to be a numeric string.

解决方案

The best way to combine rules and display custom error messages for different situations is to create a custom validator. Now if you want that to work on client-side too (it was one of my problems detailed in question B above, thanks to @Beowulfenator for the lead on this), you have to create an actual custom validator class extended from the yii2 native validator class.

Here is an example:

CustomValidator.php

<?php

namespace app\components\validators;

use Yii;
use yii\validators\Validator;

class CustomValidator extends Validator
{
    public function init() {
        parent::init();
    }

    public function validateAttribute($model, $attribute) {
        $model->addError($attribute, $attribute.' message');
    }

    public function clientValidateAttribute($model, $attribute, $view)
    {
return <<<JS
messages.push('$attribute message');
JS;
    }
}

LoginForm.php

<?php
namespace common\models;

use Yii;
use yii\base\Model;
use app\components\validators\CustomValidator;

/**
 * Login form
 */
class LoginForm extends Model
{
    public $username;
    public $password;
    public $custom;

    private $_user;


    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            // username and password are both required
            [['username', 'password'], 'required'],
            // username should be a number and of 8 digits
            [['username'], 'number', 'message'=>'{attribute} must be a number'],
            [['username'], 'string', 'length' => 8],
            // password is validated by validatePassword()
            ['password', 'validatePassword'],
            ['custom', CustomValidator::className()],
        ];
    }

    // ...

login.php

<?php

/* @var $this yii\web\View */
/* @var $form yii\bootstrap\ActiveForm */
/* @var $model \common\models\LoginForm */

use yii\helpers\Html;
use yii\bootstrap\ActiveForm;

$this->title = 'Login';
?>
<div class="site-login text-center">
    <h1><?php echo Yii::$app->name; ?></h1>

    <?php $form = ActiveForm::begin([
        'id' => 'login-form',
        'fieldConfig' => ['template' => "{label}\n{input}"],
        'enableClientValidation' => true,
        'validateOnSubmit' => true,
    ]); ?>

    <?= $form->errorSummary($model, ['header'=>'']) ?>

    <div class="row">
        <div class="col-lg-4 col-lg-offset-4">
            <div class="col-lg-10 col-lg-offset-1">

                    <div style="margin-top:40px">
                        <?= $form->field($model, 'username') ?>
                    </div>

                    <div>
                        <?= $form->field($model, 'password')->passwordInput() ?>
                    </div>

                    <div>
                        <?= $form->field($model, 'custom') ?>
                    </div>

                    <div class="form-group" style="margin-top:40px">
                        <?= Html::submitButton('Login', ['class' => 'btn btn-default', 'name' => 'login-button']) ?>
                    </div>

            </div>
        </div>
    </div>

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

</div>

这篇关于Yii2:ActiveForm:在一个字段上组合规则/多重验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
PHP最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆