Yii2中的場景(scenario)和驗證規矩(rule)

Yii2的rule用于對模子屬性舉辦驗證,scenario用戶界說差別場景下需要驗證的模子,下面這篇文章重要給大家先容了關于Yii2中場景(scenario)和驗證規矩(rule)的干系质料,文中顛末過程示例代碼先容的非常具體,需要的朋儕可以參考下。

媒介

場景,顧名思義,就是一個情況,一種局面。在yii2中也有場景,這個場景跟你所明確的場景寄義差未幾。

和用戶有交互的系統必不可少的成果包羅網絡用戶數據、校驗和措置處分。實際業務中,經常還需要將數據舉辦長期化存儲。出于安靜思量,開辟職員應當牢牢把握“客戶端的輸進都是不可信”的準則,客戶端傳過來的數據先舉辦過濾和洗濯后再存儲或轉達到內部系統。

Yii2保舉利用Model類來網絡和校驗用戶數據,長期化的ActiveRecord類是其子類。Model類的load和validate兩個要領,分辨用來網絡和校驗客戶端數據。哪些數據應當被網絡,哪些數據需要在甚么場景下驗證,便是本文的主題:場景(scenario)和驗證規矩(rule)。

下面話未幾說了,來隨著小編一起看看具體的先容吧。

系統布局

先引進一個簡略的業務系統:系統中存在門生和西席兩種腳色,數據庫中利用了三張表生活腳色信息:

user: [id, username, password, status, 其他通用屬性]

student: [id, user_id, student_no, grade, class, 其他門生屬性]

teacher: [id, user_id, work_no, title, telphone, 其他西席屬性]

實際業務不限于對這三張表的增刪查改利用。為了簡化標題,后續僅會商user和student兩張表的數據變更(給出teacher表是為了讓讀者不認為企图數據庫的人是腦殘:鮮顯著顯可以放到一張表的,為甚么要拆開!)。

門生報名

門生報名是范例的增刪查改利用,送分題。門生報名的簡要代碼示例以下:

public function actionSignup()
{
 $data = Yii::$app->request->post();
 $user = new User();
 $user->load($data);
 if ($user->save()) {
  $student = new Student([
   "user_id" => $user->id,
  ]);
  $student->load($data);
  if ($student->save()) {
   // redirect to success page
  } else {
   $user->delete();
  }
 }
 // render error page
}

信托有Yii2利用履歷的人都能憑據數據庫的字段束縛快速的把User和Student類的rules要領寫出來。比喻User類文件內容大概以下:

namespace app\models;
class User extends \yii\db\ActiveRecord
{
 public function rules()
 {
  return [   [["username", "password", "status",], "required"],
   ["username", "unique"],
   // other rules
  ];
 }
 // other method
}

界說數據的驗證規矩,這是年夜多數人對rules的第一印象,并且是一個很好的印象:它打回非法的數據,讓正常的數據進進系統中。安靜的實踐應當只管界說完整的規矩,充推行證數據。也發起每個Yii2開辟職員對內置的核心校驗器熟諳。

點竄信息

點竄信息,也是范例的增刪查改利用。實當代碼和報名差別不年夜,這里僅會商兩點:

1、用戶暗碼的驗證

注冊時會校驗用戶暗碼是不是是8-16位,暗碼的規矩大概是: ["password", "string", "length" => [8, 16]] 。明文生活暗碼是不可取的,插進數據庫時最少會做MD5加密,password變成32位。假定用戶點竄信息時未點竄暗碼,再次生活時暗碼規矩校驗墮落(長度不切合),沒法生活!

怎樣辦理這個標題呢?翻閱Yii文檔,創造白規矩中的when屬性可以救場。一種大概的驗證規矩是:

public function rules()
{
 return [
   ["password", "string", "length" => [8, 16], 'when' => function ($model) {
    return $model->isNewRecord;
   }],
   // other rules
  ];

只有在注冊(新增數據)時才校驗暗碼字段。標題辦理,美滿!

2、压迫用戶擅自改暗碼

假定有個小聰慧的家伙(比喻湯姆),創造系統是用Yii框架做的,想弄點小損壞炫耀一下程度。在發送點竄信息的表單時,湯姆增長&password=12345678這一段數據。系統利用$user->load($data)網絡用戶輸進,更新password字段,帶來以下成果:rules設置更新時不校驗暗碼字段,12345678直接作為password的值生活到數據庫中。這個利用帶來連鎖反響:用戶再次登錄時,加密過后的暗碼與數據庫中的明文暗碼不匹配,導致湯姆沒法登錄系統。煩人的是湯姆是個刺頭,登錄不上后整天騷擾客服,不省心!

怎樣樣压迫這類情況涌現呢?一種辦理的要領是压迫點竄暗碼: 

unset($data["password"]);
$user->load($data);
// 或
$password = $user->password;
$user->load($data);
$user->password = $password;

把用戶輸進的暗碼過濾掉落落,擅自點竄暗碼的標題就辦理了。

但是標題還沒有竣事:湯姆可以轉向點竄其他字段,比如說性別,身份證等。更嚴格情況是點竄student中user_id,便可以變動恣意門生的信息。事變非常嚴格,需要赶紧修復偏差。

可以憑據暗碼的要領,逐一樊籬受掩護屬性,但顯得啰嗦丟臉(固然好使)。假如受掩護屬性多,可以僅答應白名單進進,具體利用為:新增一個UpdateInfoForm類繼續Model,屬性是白名單屬性合計。用UpdateInfoForm類過濾用戶數據,校驗顛末過程后再更新到user和student中:

$form = new UpdateInfoForm();
$form->load($data);
if ($form->validate()) {
 $user->load($form->attributes);
 $student->load($form->attributes);
 // next biz
}

這類體例更優雅,但過細一想代價不小:屬性和驗證規矩要重復寫一遍;user和student生活時又重復校驗屬性。這類體例看起來優雅,實際上卻冗余又低效。

scenario的登場,美滿的辦理辦理上述標題。

場景(scenario)

分析上面標題,會創造要害點是批量賦值(massive assignment)和數據校驗(validate)兩個要領。假如對差別的場景指定賦值字段和檢驗規矩,標題就瓜熟蒂落。

Yii中的scenario有 安靜屬性 和 生動屬性 兩個見解。安靜屬性用在批量賦值的load要領,只有安靜屬性才调被賦值;生動屬性用在規矩校驗的validate要領,在生動屬性會回并且界說了校驗規矩的屬性才會被校驗。生動屬性安靜靜屬性的干系是,安靜屬性是生動屬性的子集。

\yii\base\Model類界說了默許場景:SCENARIO_DEFAULT(值為default)。默許場景下,呈如今rules要領中的屬性既是生動屬性,又是安靜屬性(這句話底子正確,看后續解釋)。為差別場景指定生動屬性、安靜屬性和校驗器,可以顛末過程包圍senarios或rules兩個要領實現(險些每個Model類都市重寫rules要領,senarios用得少)。

rules

先看rules要領。默許的屬性加校驗器界說體例,讓每個屬性既是安靜屬性,也是生動屬性。假如想讓某個屬性不是安靜屬性(不克不及顛末過程load批量賦值),在屬性名前加感喟號!便可。比喻student中的user_id字段:

public function rules()
{
 return [
  ["!user_od", "required"],
  ["!user_id", "integer"],
  ["!user_od", "unique"],
  // other rules
 ];
}

user_id是生動屬性,在寫進數據庫時會被校驗。但它不是安靜屬性,不克不及顛末過程load要領舉辦賦值,辦理了安靜隱患。

再看rules要領按場景分辨校驗器規矩的做法:界說校驗器時on屬性指定規矩在哪些場景下見效,except屬性則打掃一些場景(假如不指定on和except,規矩對全部場景見效)。比喻:

public function rules()
{
 return [
  ["password", "string", "length" => [8, 16], "on" => ["signup"]], // 僅在signup場景時才被驗證
  ["status", "integer", "except" => ["signup"], // 除signup場景,其他情況都校驗
  // other rules
 ];
}

在本來底子上新增感喟號和on/except屬性,非常輕便的就界說了非安靜屬性和分場景指定校驗規矩。

scenarios

別的一種更明確界說安靜屬性和生動屬性的做法是重寫scenarios要領。scenarios要領返回一個數組,數組的鍵是場景名稱,值是生動屬性湊集(包飯安靜屬性)。比喻student表的大概實現以下:

public function scenarios()
{
 return [
  self::SCENARIO_DEFAULT => ["!user_id", "grade", "class", xxxx],
  "update" => ["grade", "class", xxxx],
 ];
}

默許情況下(門生報名),年級、班級這些信息是安靜屬性,但user_id不是,只能在程序內部賦值,并在插進數據時被校驗;在點竄信息時,user_id不是生動屬性,既不克不及被批量賦值,也不需要校驗(究竟上它不應當轉變)。

scenarios要領只能界說生動屬性安靜靜屬性,沒法界說校驗規矩,需要和rules共同利用。

總結

金肯界說美滿的數據校驗規矩

業務宏年夜時界說多個場景,過細為每個場景界說安靜屬性和校驗規矩

優先利用rules;屬性較多、rules宏年夜時,可以共同scenarios要領敏銳理清安靜屬性和生動屬性

好了,以上就是這篇文章的全部內容了,希看本文的內容對大家的學習或事變具有確定的參考學習代價,假如有疑問大家可以留言互換,謝謝大家對腳本之家的撐持。


無數據提示還沒有評論,樓主喊你快往搶前排~~~我要評論
微信掃碼登陸