Yii2:如何为activeform使用自定义验证功能?

时间:2015-01-06 18:48:15

标签: forms validation yii2

在我的表单模型中,我有一个自定义验证函数,用于以这种方式定义的字段

class SignupForm extends Model
{
    public function rules()
    {
        return [
            ['birth_date', 'checkDateFormat'],

            // other rules
        ];
    }

    public function checkDateFormat($attribute, $params)
    {
        // no real check at the moment to be sure that the error is triggered
        $this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
    }
}

当我按下提交按钮时,错误消息不会显示在表单视图中的字段下,而其他规则则会显示所需的电子邮件和密码。

我正在使用注册本机表单,所以为了确保它不是一个存档问题,我已经设置了规则

['username', 'checkDateFormat']

并删除了与用户名字段相关的所有其他规则,但该消息并未显示。

我已尝试将任何内容作为参数传递给checkDateFormat,我已尝试将字段的名称明确传递给addError()

$this->addError('username', '....');

但没有出现。

设置自定义验证功能的正确方法是什么?

12 个答案:

答案 0 :(得分:10)

您是否阅读过文档?

  

根据上述验证步骤,属性将是   当且仅当它是在中声明的活动属性时验证   scenario()并与一个或多个活动规则相关联   在rules()中声明。

所以你的代码应该是这样的:

class SignupForm extends Model
{
    public function rules()
    {
        return [
            ['birth_date', 'checkDateFormat'],

            // other rules
        ];
    }

    public function scenarios()
    {
        $scenarios = [
            'some_scenario' => ['birth_date'],
        ];

        return array_merge(parent::scenarios(), $scenarios);
    }

    public function checkDateFormat($attribute, $params)
    {
        // no real check at the moment to be sure that the error is triggered
        $this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
    }
}

在控制器设置场景中,例如:

$signupForm = new SignupForm(['scenario' => 'some_scenario']);

答案 1 :(得分:6)

尝试在空字段上强制验证

['birth_date', 'checkDateFormat', 'skipOnEmpty' => false, 'skipOnError' => false],

另外,请确保您没有为视图中的birth_date字段指定ID。

如果您确实拥有birth_date的ID,则需要指定selectors

<?= $form->field($model, 'birth_date', ['selectors' => ['input' => '#myBirthDate']])->textInput(['id' => 'myBirthDate']) ?>

答案 2 :(得分:6)

要在yii 2中进行自定义验证,您可以在模型中编写自定义函数并在规则中分配该函数。 例如。我必须在password字段中应用密码标准,然后我会在模型中这样写。

public function rules()
{
    return [
        ['new_password','passwordCriteria'],
    ];
}

public function passwordCriteria()
{
    if(!empty($this->new_password)){
        if(strlen($this->new_password)<8){
            $this->addError('new_password','Password must contains eight letters one digit and one character.');
        }
        else{
            if(!preg_match('/[0-9]/',$this->new_password)){
                $this->addError('new_password','Password must contain one digit.');
            }
            if(!preg_match('/[a-zA-Z]/', $this->new_password)){
                $this->addError('new_password','Password must contain one character.');
            }
        }
    }
}

参考文献: - form validation in yii 2

答案 3 :(得分:5)

如果从类Model扩展,则需要在某处触发$model->validate()

答案 4 :(得分:2)

使用CRUD发生器时,我偶然发现了这一点。生成的actionCreate()函数不包含模型验证调用,因此永远不会调用自定义验证器。此外,_form不包含错误摘要。

所以将错误摘要添加到_form。

<?= $form->errorSummary($model); ?>

...并将验证调用 - $ model-&gt; validate() - 添加到控制器操作

public function actionCreate()
{
    $model = new YourModel();

    if ($model->load(Yii::$app->request->post()) && $model->validate()) {...

答案 5 :(得分:1)

您需要从控制器渲染模型。无需在视图中初始化模型。在控制器中,您需要调用验证功能

答案 6 :(得分:1)

您确定addError的第一个参数不应该像这样吗

$this->addError(**'attribute'**, Yii::t('user', 'You entered an invalid date format.'));

答案 7 :(得分:1)

我有共同的问题。

在验证功能中:

public function checkDateFormat($attribute, $params)
    {
        // no real check at the moment to be sure that the error is triggered
        $this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
    }

$ params根本没有任何价值。它实际上总是等于Null。您必须在函数中检查属性值:

public function checkDateFormat($attribute, $params)
{
    if($this->birth_date == False)
    {
        $this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
    }
}

这对我有用。

答案 8 :(得分:1)

虽然这是一个老帖子,但我认为我应该回答。

您应该创建一个自定义验证器类并创建一个支持客户端验证的验证器,您应该实现yii\validators\Validator::clientValidateAttribute()方法,该方法返回一段在客户端执行验证的JavaScript代码。在JavaScript代码中。

  

您可以使用以下预定义变量:

     

attribute:要验证的属性的名称。

     

value:正在验证的值。

     

messages:用于保存验证错误消息的数组   属性。

     

deferred:一个可以推送延迟对象的数组   (在下一小节中解释)。

这意味着您可以使用messages数组在此方法的javascript代码块中在运行时将消息推送到客户端。

我将创建一个包含虚拟检查的类,可以按照您希望的方式替换它们。并根据您的yii2 namespaceadvanced更改basic

Custom Client-side Validator

namespace common\components;
use yii\validators\Validator;

class DateFormatValidator extends Validator{
public function init() {
        parent::init ();
        $this->message = 'You entered an invalid date format.';
    }

    public function validateAttribute( $model , $attribute ) {

        if ( /*SOME CONDITION TO CHECK*/) {
            $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 ($("#DATE-1").val()=="" || $("#DATE-2").val() =="") {
    messages.push($message);
}
JS;
    }
}

然后在模型中SigupForm添加rule

['birth_date', 'common\components\DateFormatValidator'],

Deferred Validation

你甚至可以在clientValidateAttribute函数内添加ajax调用,并且在ajax调用结果的基础上你可以将消息推送到客户端,但你可以使用yii提供的deferred对象这是一个Deferred对象数组,您可以在该数组中推送您的调用,或者显式创建Deferred对象并调用其resolve()方法。

Default Yii's deferred Object

public function clientValidateAttribute($model, $attribute, $view)
{
    return <<<JS
        deferred.push($.get("/check", {value: value}).done(function(data) {
            if ('' !== data) {
                messages.push(data);
            }
        }));
JS;
}

有关Deferred Validation

的更多信息

答案 9 :(得分:0)

如果您不为模型使用方案,则必须将属性标记为“安全”:

    ['birth_date','safe'],
    ['birth_date', 'checkDateFormat'],

另一方面,您可以将其用于日期验证:

    ['birth_date','safe'],
    [['birth_date'],'date', 'format'=>'php:Y-m-d'],

您可以根据需要更改格式。

答案 10 :(得分:-1)

您是否有机会使用客户端验证?如果你这样做,你必须编写一个验证输入的javascript函数。你可以在这里看到他们是如何做到的:

http://www.yiiframework.com/doc-2.0/guide-input-validation.html#conditional-validation

另一个解决方案是禁用客户端验证,使用ajax验证,这也应该带回错误。

另外请确保您没有覆盖输入的模板,这意味着如果您覆盖了输入模板,请确保其中仍有{error}。

答案 11 :(得分:-2)

你对规则的语法应该是这样的人,

[['birth_date'], 'checkDateFormat']

不是这个

['birth_date', 'checkDateFormat']

所以在你的情况下,它应该如下所示

...
class SignupForm extends Model
{
    public function rules()
    {
        // Notice the different with your previous code here
        return [
            [['birth_date'], 'checkDateFormat'], 

            // other rules
        ];
    }

    public function checkDateFormat($attribute, $params)
    {
        // no real check at the moment to be sure that the error is triggered
        $this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
    }
}