業務需求
在我們的日常需求中,會有這種
數據表中存在圖片字段,爲必填,需要在操作過程中做到
- 創建數據時,圖片字段必須
- 修改數據時,圖片字段如果不傳,就不修改
解決方案
業務數據操作
如果要保持原來的圖片數據,那隻要修改的時候帶着原來的參數即可
- 加載表單時帶原來的數據
- 圖片數據放在隱藏的文本域中
- 提交表單時如果圖片上傳的字段沒有值,就將原來的圖片數據從隱藏文本域中拿出來
這樣的操作當然能滿足需求,但是太複雜了
定義場景setScenario
在Yii的數據操作中,一般的邏輯如下
- 判斷是否有提交數據
Yii::$app->request->post()
- 表單數據加載到模型model中
$model->load(Yii::$app->request->post())
- 保存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 源碼