简体   繁体   English

Yii2:ActiveForm:在一个字段上组合规则/多次验证

[英]Yii2: ActiveForm: combine rules / multiple validation on one field

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: 我为上面的同一字段设置了2条规则:

[['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 : 我想的形式为以下3分场景 的情况显示不同的错误消息:

  1. The provided value is neither a number, nor 8 characters (digits). 提供的值既不是数字,也不是8个字符(数字)。
  2. The provided value is a number, but is not of 8 characters (digits). 提供的值是数字,但不能是8个字符(数字)。
  3. The provided value is not a number, but is of 8 characters (digits). 提供的值不是数字,而是8个字符(数字)。

My question is 2 fold: 我的问题是2折:

A. Is there a way to combine these rules in any standard, Yii2 way. Yii2 :有没有一种方法可以以任何标准Yii2方式组合这些规则。
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. B. 在我之前的问题中,我试图设置一个自定义验证器(解决此问题的明显方法),但是它很简单地被忽略了。 The only way I could make it validate was if I added the username field to a scenario. 我可以使其验证的唯一方法是,是否将username名字段添加到方案中。 However, once I added password too, it was again ignored. 但是,一旦我也添加了password ,便再次被忽略。 Any reason's for this that you can think of? 您能想到的任何原因是什么? EDIT : skipOnError = false changed nothing at all in this behaviour. 编辑skipOnError = false在此行为上完全没有改变。

So please, when you answer, make sure you test it preferably in yii2/advanced ; 因此,请在回答时确保最好在yii2/advancedyii2/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. 编辑 :为清楚起见,我只允许使用8个字符(数字)的数字,因此它们可能以0开头。 00000001 , or 00000000 for that matter. 0000000100000000 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. 现在,如果您也想在客户端运行它(这是我在上面问题B中详细介绍的问题之一,这要感谢@Beowulfenator的帮助),您必须创建一个从yii2本机扩展的实际自定义验证器类验证器类。

Here is an example: 这是一个例子:

CustomValidator.php 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 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 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>

Finally you need this : 最后,您需要:

  • the value is required 该值是必需的
  • the value must be a string of 8 chars 该值必须是8个字符的字符串
  • the value must contains only digits 该值只能包含数字

So you should simply try : 因此,您应该尝试:

['username', 'required'],
['username', 'string', 'min' => 8, 'max' => 8],
['username', 'match', 'pattern' => '/^[0-9]{8}$/', 'message'=>'{attribute} must be a number'],

Yii2 ignores your validation rules may because you duplicated not only attribue but also types. Yii2会忽略您的验证规则,可能是因为您不仅重复了属性而且还重复了类型。 With number validation, i think you should use min/max option to validate number length. 通过数字验证,我认为您应该使用最小/最大选项来验证数字长度。

For this case: 对于这种情况:

'min'=>10000000,'max'=>99999999

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM