Yii2 中的自定义属性验证

Custom attribute validation in Yii2

我有模型表单 (SomeForm) 和自定义验证函数:

use yii\base\Model; 
class SomeForm extends Model
{
      public $age;
      public function custom_validation($attribute, $params){
             if($this->age < 18){
                    $this->addError($attribute, 'Some error Text');
                    return true;
             }
             else{
                     return false;
             }
      }
      public function rules(){
             return [
                 ['age', 'custom_validation']
             ];
      }
}

我在 rules() 函数中使用了这个 custom_validation 但表单甚至提交了具有 age 属性的任何值。

表格如下:

age.php

<?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(); ?>

和控制器:

use yii\web\Controller;

class SomeController extends Controller
{
     //this controller is just for rendering
     public function actionIndex(){
             return $this->render('age');
     }
     public function actionSubmit(){
             $model = new SomeForm();
             if($model->load(Yii::$app->request->post()){
                   //do something here
             }
     }
}

您不需要 return 任何东西,只需将错误添加到属性中就足够了。

从版本 2.0.11 开始,您可以立即使用 yii\validators\InlineValidator::addError() for adding errors instead of using $this. That way the error message can be formatted using yii\i18n\I18N::format()

在错误消息中使用{attribute}{value}来引用属性标签(无需手动获取)和相应的属性值:

我怀疑你的问题是你错过了 $formModel->validate() 因为在上面给出的模型中扩展了 yii\base\Model 而不是 \yii\db\ActiveRecord 并且你必须保存一些其他 ActiveRecord 模型并想在保存 ActiveRecord 模型之前验证此 FormModel,您必须调用 $formModel->validate() 来检查是否提供了有效输入并触发模型验证将 post 数组加载到模型后。

另一件需要注意的事情是,默认情况下,如果内联验证器的关联属性接收到空输入,或者如果它们已经未能通过某些验证规则,则不会应用内联验证器。如果您想确保始终应用规则,您可以在规则声明中将 skipOnEmpty and/or skipOnError 属性配置为 false

您的模型应该如下所示您在模型定义中缺少 namespace 如果这不仅仅是故意的或由于示例代码。只需根据它所在的路径更新你的命名空间。

namespace frontend\models;

use yii\base\Model; 
class SomeForm extends Model
{
      public $age;
      const AGE_LIMIT=18;

      public function rules(){
             return [
                 ['age', 'custom_validation','skipOnEmpty' => false, 'skipOnError' => false]
             ];
      }

      public function custom_validation($attribute, $params,$validator){
          if($this->$attribute< self::AGE_LIMIT){
             $validator->addError($this, $attribute, 'The value "{value}" is not acceptable for {attribute}, should be greater than '.self::AGE_LIMIT.'.');
           }
      }
}

你的 controller/action 应该看起来像

public function actionTest()
    {
        //use appropriate namespace
        $formModel = new \frontend\models\SomeForm();
        $model= new \frontend\models\SomeActiveRecordModel();

        if ($formModel->load(Yii::$app->request->post()) && $model->load(Yii::$app->request->post())) {
            if ($formModel->validate()) {
             // your code after validation to save other ActiveRecord model
             if($model->save()){
              Yii::$app->session->setFlash('success','Record added succesfully.')
             }
            }
        }

        return $this->render('test', ['model' => $model,'formModel'=>$formModel]);
    }

视图文件中的输入字段 age 应使用 $formMoedl 对象

echo $form->field($formModel, 'age')->textInput();