【Yii2】模型Model中使用rules規則定義場景setScenario限制規則

業務需求

在我們的日常需求中,會有這種

數據表中存在圖片字段,爲必填,需要在操作過程中做到

  • 創建數據時,圖片字段必須
  • 修改數據時,圖片字段如果不傳,就不修改

解決方案

業務數據操作

如果要保持原來的圖片數據,那隻要修改的時候帶着原來的參數即可

  1. 加載表單時帶原來的數據
  2. 圖片數據放在隱藏的文本域中
  3. 提交表單時如果圖片上傳的字段沒有值,就將原來的圖片數據從隱藏文本域中拿出來

這樣的操作當然能滿足需求,但是太複雜了

定義場景setScenario

在Yii的數據操作中,一般的邏輯如下

  1. 判斷是否有提交數據Yii::$app->request->post()
  2. 表單數據加載到模型model中 $model->load(Yii::$app->request->post())
  3. 保存model的數據 $model->save()

重點時第三步,在save的操作中,默認執行驗證操作,判斷提交的數據是否如何model中的規則

    /**
     * Saves the current record.
     *
     * This method will call [[insert()]] when [[isNewRecord]] is `true`, or [[update()]]
     * when [[isNewRecord]] is `false`.
     *
     * For example, to save a customer record:
     *
     * ```php
     * $customer = new Customer; // or $customer = Customer::findOne($id);
     * $customer->name = $name;
     * $customer->email = $email;
     * $customer->save();
     * ```
     *
     * @param bool $runValidation whether to perform validation (calling [[validate()]])
     * before saving the record. Defaults to `true`. If the validation fails, the record
     * will not be saved to the database and this method will return `false`.
     * @param array $attributeNames list of attribute names that need to be saved. Defaults to null,
     * meaning all attributes that are loaded from DB will be saved.
     * @return bool whether the saving succeeded (i.e. no validation errors occurred).
     */
    public function save($runValidation = true, $attributeNames = null)
    {
        if ($this->getIsNewRecord()) {
            return $this->insert($runValidation, $attributeNames);
        }

        return $this->update($runValidation, $attributeNames) !== false;
    }

$runValidation = true 會驗證規則,如下

    public function rules()
    {
        return [
            [['name','sort'], 'required'],
            [['classify', 'is_recommend', 'sort', 'status', 'create_at', 'update_at'], 'integer'],
            [['name'], 'string', 'max' => 64],
            [['images'], 'string', 'max' => 255],
        ];
    }

這裏清楚的標記了哪些字段是有必須的,哪些字段的長度最大是多少

設定場景setScenario

我們先看源碼model中的rules的部分

    /**
     * Returns the validation rules for attributes.
     *
     * Validation rules are used by [[validate()]] to check if attribute values are valid.
     * Child classes may override this method to declare different validation rules.
     *
     * Each rule is an array with the following structure:
     *
     * ```php
     * [
     *     ['attribute1', 'attribute2'],
     *     'validator type',
     *     'on' => ['scenario1', 'scenario2'],
     *     //...other parameters...
     * ]
     * ```
     *
     * where
     *
     *  - attribute list: required, specifies the attributes array to be validated, for single attribute you can pass a string;
     *  - validator type: required, specifies the validator to be used. It can be a built-in validator name,
     *    a method name of the model class, an anonymous function, or a validator class name.
     *  - on: optional, specifies the [[scenario|scenarios]] array in which the validation
     *    rule can be applied. If this option is not set, the rule will apply to all scenarios.
     *  - additional name-value pairs can be specified to initialize the corresponding validator properties.
     *    Please refer to individual validator class API for possible properties.
     *
     * A validator can be either an object of a class extending [[Validator]], or a model class method
     * (called *inline validator*) that has the following signature:
     *
     * ```php
     * // $params refers to validation parameters given in the rule
     * function validatorName($attribute, $params)
     * ```
     *
     * In the above `$attribute` refers to the attribute currently being validated while `$params` contains an array of
     * validator configuration options such as `max` in case of `string` validator. The value of the attribute currently being validated
     * can be accessed as `$this->$attribute`. Note the `$` before `attribute`; this is taking the value of the variable
     * `$attribute` and using it as the name of the property to access.
     *
     * Yii also provides a set of [[Validator::builtInValidators|built-in validators]].
     * Each one has an alias name which can be used when specifying a validation rule.
     *
     * Below are some examples:
     *
     * ```php
     * [
     *     // built-in "required" validator
     *     [['username', 'password'], 'required'],
     *     // built-in "string" validator customized with "min" and "max" properties
     *     ['username', 'string', 'min' => 3, 'max' => 12],
     *     // built-in "compare" validator that is used in "register" scenario only
     *     ['password', 'compare', 'compareAttribute' => 'password2', 'on' => 'register'],
     *     // an inline validator defined via the "authenticate()" method in the model class
     *     ['password', 'authenticate', 'on' => 'login'],
     *     // a validator of class "DateRangeValidator"
     *     ['dateRange', 'DateRangeValidator'],
     * ];
     * ```
     *
     * Note, in order to inherit rules defined in the parent class, a child class needs to
     * merge the parent rules with child rules using functions such as `array_merge()`.
     *
     * @return array validation rules
     * @see scenarios()
     */
    public function rules()
    {
        return [];
    }

其中 關於場景的部分,通過on定義場景

'on' => ['scenario1', 'scenario2'],

可以應用規則。 如果未設置此選項,則該規則將適用於所有場景。

rule can be applied. If this option is not set, the rule will apply to all scenarios.

當規則對應的場景時,規則會被採用

  ['password', 'compare', 'compareAttribute' => 'password2', 'on' => 'register'],
   ['password', 'authenticate', 'on' => 'login'],

那麼,最後我們得到關於圖片的字段約束規則如下

            [['images'], 'required', 'on' => ['create'],'enableClientValidation'=>false],
            [['images'], 'defaultHead', 'skipOnEmpty' => false, 'on' => ['edit']],

參考資料

  • Yii2 源碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章