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

Yii Model 預設值設定兩大技巧:rules() default 規則與 beforeSave() 事件注入

     編輯:PHP 綜合知識

場景:自動填充非表單欄位

訂單編號、建立時間、操作用戶 ID 等欄位不在表單中,需在儲存前自動賦值。

方法一:rules() 陣列中使用 default 驗證器

// models/Order.php
public function rules() {
    return [
        ['order_no, created_at, user_id', 'required'], // 邏輯上必填,但由系統自動產生
        ['user_id', 'numerical', 'integerOnly' => true],
        // 關鍵:default 驗證器在驗證階段自動填充
        ['created_at', 'default', 'value' => date('Y-m-d H:i:s')],
        ['order_no', 'default', 'value' => function() { return 'ORD' . date('YmdHis') . rand(100,999); }],
        ['status', 'default', 'value' => 0], // 預設狀態
        // 搜尋場景安全屬性
        ['id, order_no, created_at, user_id, status', 'safe', 'on' => 'search'],
    ];
}
  • default 驗證器在 validate() 時執行,若屬性為 null/未設定,則注入 value。
  • value 可為純量或 可呼叫物件(PHP 5.3+ 匿名函式),支援動態生成。
  • 優點:聲明式、集中管理、驗證階段即生效、可搭配 skipOnEmpty 控制。

方法二:beforeSave() 事件覆寫

// models/Order.php
protected function beforeSave() {
    if ($this->isNewRecord) {
        $this->order_no = 'ORD' . date('YmdHis') . rand(100,999);
        $this->created_at = date('Y-m-d H:i:s');
        $this->user_id = Yii::app()->user->id; // 取得當前登入用戶
        $this->ip = Yii::app()->request->userHostAddress;
    }
    $this->updated_at = date('Y-m-d H:i:s'); // 每次更新都刷新
    return parent::beforeSave(); // 必須返回 true 才會繼續儲存
}
  • beforeSave() 在 save() 內部、驗證通過後、資料庫寫入前呼叫。
  • 可存取 Yii::app()->user、request 等應用元件,適合需上下文資訊的欄位。
  • 關鍵:必須 return parent::beforeSave()(或 true),否則儲存中斷。
  • 優點:邏輯集中、可執行複雜運算、區分新增/更新($this->isNewRecord)。

兩者差異與選擇指南

進階組合:雙重保險

public function rules() {
    return [
        ['created_at', 'default', 'value' => date('Y-m-d H:i:s')], // 第一道防線
        // ...
    ];
}
protected function beforeSave() {
    if ($this->isNewRecord && empty($this->created_at)) {
        $this->created_at = date('Y-m-d H:i:s'); // 第二道防線,防止規則被跳過
    }
    return parent::beforeSave();
}

常見錯誤

  1. beforeSave 忘記 return true:導致資料不寫入、無錯誤訊息,極難排查。
  2. default value 用字串卻需動態:'value' => date('Y-m-d') 會在類別載入時固定,必須用匿名函式 function() { return date(...); }。
  3. 覆寫 rules() 未呼叫 parent::rules():導致父類驗證規則遺失(如基類的安全屬性)。
  4. 屬性未宣告:Active Record 需在類別中宣告 public $created_at; 或資料表有對應欄位。

Yii 2.0 對應寫法

// Yii 2 ActiveRecord
public function rules() {
    return [
        [['created_at', 'order_no'], 'default', 'value' => function() { return date('Y-m-d H:i:s'); }],
        ['order_no', 'default', 'value' => function() { return 'ORD' . date('YmdHis') . rand(100,999); }],
    ];
}
public function beforeSave($insert) {
    if (parent::beforeSave($insert)) {
        if ($insert) {
            $this->user_id = Yii::$app->user->id;
            $this->ip = Yii::$app->request->userIP;
        }
        $this->updated_at = date('Y-m-d H:i:s');
        return true;
    }
    return false;
}

總結

rules() default 適合無上下文依賴的固定/動態預設值,beforeSave() 適合需用戶身分、請求資訊、區分新增更新的複雜賦值。實務上常結合使用:規則提供基礎預設,事件處理上下文相關欄位,並作為最後防線確保資料完整性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
維度rules() defaultbeforeSave()
執行時機validate() 階段save() 內部,驗證後
存取應用元件不可(靜態上下文)可(Yii::app()->user 等)
動態值支援可(匿名函式)可(任意 PHP 邏輯)
區分新增/更新不可直接區分可 (isNewRecord)
適用欄位固定預設、時間戳、隨機碼用戶 ID、IP、關聯資料、複雜計算
可見性規則集中可見方法內部,需閱讀代碼