首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

Yii2 ActiveForm 自定義驗證規則實戰:場景化條件驗證、屬性級別邏輯與最佳實踐

     編輯:PHP 相關知識

超越內置驗證器:掌握 Yii2 Model 規則的靈活擴展機制

Yii2 yii\base\Model::rules() 支援閉包、方法名、獨立驗證器類三種自定義方式。本文以「條件必填」為核心場景,演示如何實現「字段 A 為 1 時,字段 B 必填;A 為 2 時,B 可選」的業務邏輯。

場景定義

  • 字段 type (A):下拉選擇,值 1|2
  • 字段 content (B):文本域
  • 業務規則:type === 1 → content 必填;type === 2 → content 可選

方案一:內聯方法(最常用、最簡潔)

<?php
namespace app\models;

use yii\base\Model;

class ArticleForm extends Model
{
    public $type;
    public $content;

    public function rules()
    {
        return [
            ['type', 'required'],
            ['type', 'in', 'range' => [1, 2]],
            ['content', 'validateContentByType'], // 方法名驗證器
        ];
    }

    /**
     * 自定義驗證方法
     * @param string $attribute 當前驗證屬性名 (content)
     * @param mixed $params 規則中額外參數
     */
    public function validateContentByType($attribute, $params)
    {
        if ($this->type == 1 && empty($this->$attribute)) {
            $this->addError($attribute, '當類型為 1 時,內容不能為空。');
        }
    }
}

方案二:閉包驗證器(內聯邏輯、無需額外方法)

public function rules()
{
    return [
        ['type', 'required'],
        ['type', 'in', 'range' => [1, 2]],
        ['content', function ($attribute, $params) {
            if ($this->type == 1 && empty($this->$attribute)) {
                $this->addError($attribute, '類型 1 必填內容。');
            }
        }],
    ];
}

方案三:獨立驗證器類(跨模型復用、單元測試友好)

<?php
namespace app\validators;

use yii\validators\Validator;

class RequiredWhenValidator extends Validator
{
    public $whenProperty;   // 觸發條件屬性名
    public $whenValue;      // 觸發條件值
    public $message = '{attribute} 在條件滿足時必填。';

    public function validateAttribute($model, $attribute)
    {
        if ($model->{$this->whenProperty} == $this->whenValue && empty($model->$attribute)) {
            $this->addError($model, $attribute, $this->message);
        }
    }
}
// 模型中使用
use app\validators\RequiredWhenValidator;

public function rules()
{
    return [
        ['type', 'required'],
        ['type', 'in', 'range' => [1, 2]],
        ['content', RequiredWhenValidator::class, 'whenProperty' => 'type', 'whenValue' => 1],
    ];
}

進階技巧

  1. 場景:['content', 'validateContentByType', 'on' => 'publish'] 僅在 $model->validate('publish') 時觸發。
  2. 多屬性驗證:['content, images', 'validateMedia'] 同時驗證多欄位。
  3. 客戶端驗證:實現 clientValidateAttribute() 返回 JS 代碼,實現前端即時校驗(需載入 yii.activeForm.js)。
  4. 條件屬性為空:$this->type === null 視為條件不滿足,跳過驗證。

ActiveForm 視圖渲染

<?php
use yii\widgets\ActiveForm;
use yii\helpers\Html;

$form = ActiveForm::begin(['id' => 'article-form']);
echo $form->field($model, 'type')->dropDownList([1 => '類型一(必填內容)', 2 => '類型二(可選)']);
echo $form->field($model, 'content')->textarea(['rows' => 6]);
echo Html::submitButton('提交', ['class' => 'btn btn-primary']);
ActiveForm::end();

常見坑點

現象原因修正
驗證不生效方法名拼寫錯誤 / 未返回 rules()檢查拼寫、確保 return
addError 不顯示屬性名不匹配 / 視圖未輸出 $form->field()確保 $attribute 與 field 名一致
條件屬性未載入$this->type 為 null (未在 rules 中聲明)條件屬性也需在 rules 中聲明 (如 required/in)

總結

Yii2 自定義驗證三板斧:內聯方法(項目內單一邏輯)、閉包(極簡臨時邏輯)、獨立類(跨項目復用/測試)。善用 addError()、scenarios()、clientValidateAttribute() 構建健壯、用戶友好的表單驗證體系。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved