最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Yii2中的場景(scenario)和驗證規(guī)則(rule)詳解

 更新時間:2018年01月14日 11:38:10   作者:tlanyan  
Yii2的rule用于對模型屬性進行驗證,scenario用戶定義不同場景下需要驗證的模型,下面這篇文章主要給大家介紹了關(guān)于Yii2中場景(scenario)和驗證規(guī)則(rule)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下。

前言

場景,顧名思義,就是一個情景,一種場面。在yii2中也有場景,這個場景跟你所理解的場景含義差不多。

和用戶有交互的系統(tǒng)必不可少的功能包括收集用戶數(shù)據(jù)、校驗和處理。實際業(yè)務(wù)中,往往還需要將數(shù)據(jù)進行持久化存儲。出于安全考慮,開發(fā)人員應(yīng)當牢牢把握“客戶端的輸入都是不可信”的準則,客戶端傳過來的數(shù)據(jù)先進行過濾和清洗后再存儲或傳遞到內(nèi)部系統(tǒng)。

Yii2推薦使用Model類來收集和校驗用戶數(shù)據(jù),持久化的ActiveRecord類是其子類。Model類的load和validate兩個方法,分別用來收集和校驗客戶端數(shù)據(jù)。哪些數(shù)據(jù)應(yīng)該被收集,哪些數(shù)據(jù)需要在什么場景下驗證,便是本文的主題:場景(scenario)和驗證規(guī)則(rule)。

下面話不多說了,來隨著小編一起看看詳細的介紹吧。

系統(tǒng)結(jié)構(gòu)

先引入一個簡單的業(yè)務(wù)系統(tǒng):系統(tǒng)中存在學生和教師兩種角色,數(shù)據(jù)庫中使用了三張表保存角色信息:

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

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

teacher: [id, user_id, work_no, title, telphone, 其他教師屬性]

實際業(yè)務(wù)不限于對這三張表的增刪查改操作。為了簡化問題,后續(xù)僅討論user和student兩張表的數(shù)據(jù)變更(給出teacher表是為了讓讀者不認為設(shè)計數(shù)據(jù)庫的人是腦殘:明明可以放到一張表的,為什么要拆開?。?。

學生報名

學生報名是典型的增刪查改操作,送分題。學生報名的簡要代碼示例如下:

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使用經(jīng)驗的人都能根據(jù)數(shù)據(jù)庫的字段約束快速的把User和Student類的rules方法寫出來。例如User類文件內(nèi)容可能如下:

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

定義數(shù)據(jù)的驗證規(guī)則,這是大多數(shù)人對rules的第一印象,并且是一個很好的印象:它打回非法的數(shù)據(jù),讓正常的數(shù)據(jù)進入系統(tǒng)中。安全的實踐應(yīng)該盡量定義完整的規(guī)則,充分驗證數(shù)據(jù)。也建議每一個Yii2開發(fā)人員對內(nèi)置的核心校驗器熟悉。

修改信息

修改信息,也是典型的增刪查改操作。實現(xiàn)代碼和報名差別不大,這里僅討論兩點:

1、用戶密碼的驗證

注冊時會校驗用戶密碼是否8-16位,密碼的規(guī)則可能是: ["password", "string", "length" => [8, 16]] 。明文保存密碼是不可取的,插入數(shù)據(jù)庫時至少會做MD5加密,password變成32位。假設(shè)用戶修改信息時未修改密碼,再次保存時密碼規(guī)則校驗出錯(長度不符合),無法保存!

怎么解決這個問題呢?翻閱Yii文檔,發(fā)現(xiàn)了規(guī)則中的when屬性可以救場。一種可能的驗證規(guī)則是:

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

只有在注冊(新增數(shù)據(jù))時才校驗密碼字段。問題解決,完美!

2、防止用戶私自改密碼

假設(shè)有個小聰明的家伙(例如湯姆),發(fā)現(xiàn)系統(tǒng)是用Yii框架做的,想搞點小破壞炫耀一下水平。在發(fā)送修改信息的表單時,湯姆增加&password=12345678這一段數(shù)據(jù)。系統(tǒng)使用$user->load($data)收集用戶輸入,更新password字段,帶來如下后果:rules設(shè)置更新時不校驗密碼字段,12345678直接作為password的值保存到數(shù)據(jù)庫中。這個操作帶來連鎖反應(yīng):用戶再次登錄時,加密過后的密碼與數(shù)據(jù)庫中的明文密碼不匹配,導致湯姆無法登錄系統(tǒng)。煩人的是湯姆是個刺頭,登錄不上后整天騷擾客服,不省心!

怎么樣防止這種情況出現(xiàn)呢?一種解決的方法是阻止修改密碼:

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

把用戶輸入的密碼過濾掉,私自修改密碼的問題就解決了。

但是問題還沒有結(jié)束:湯姆可以轉(zhuǎn)向修改其他字段,比如說性別,身份證等。更嚴重情況是修改student中user_id,就可以更改任意學生的信息。事情十分嚴重,需要馬上修復(fù)漏洞。

可以按照密碼的方法,逐個屏蔽受保護屬性,但顯得啰嗦難看(雖然好使)。如果受保護屬性多,可以僅允許白名單進入,具體操作為:新增一個UpdateInfoForm類繼承Model,屬性是白名單屬性合計。用UpdateInfoForm類過濾用戶數(shù)據(jù),校驗通過后再更新到user和student中:

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

這種方式更優(yōu)雅,但仔細一想代價不?。簩傩院万炞C規(guī)則要重復(fù)寫一遍;user和student保存時又重復(fù)校驗屬性。這種方式看起來優(yōu)雅,實際上卻冗余又低效。

scenario的登場,完美的解決解決上述問題。

場景(scenario)

分析上面問題,會發(fā)現(xiàn)關(guān)鍵點是批量賦值(massive assignment)和數(shù)據(jù)校驗(validate)兩個方法。如果對不同的場景指定賦值字段和檢驗規(guī)則,問題就迎刃而解。

Yii中的scenario有 安全屬性 和 活躍屬性 兩個概念。安全屬性用在批量賦值的load方法,只有安全屬性才能被賦值;活躍屬性用在規(guī)則校驗的validate方法,在活躍屬性集中并且定義了校驗規(guī)則的屬性才會被校驗。活躍屬性和安全屬性的關(guān)系是,安全屬性是活躍屬性的子集。

\yii\base\Model類定義了默認場景:SCENARIO_DEFAULT(值為default)。默認場景下,出現(xiàn)在rules方法中的屬性既是活躍屬性,又是安全屬性(這句話基本正確,看后續(xù)解釋)。為不同場景指定活躍屬性、安全屬性以及校驗器,可以通過覆蓋senarios或rules兩個方法實現(xiàn)(幾乎每個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是活躍屬性,在寫入數(shù)據(jù)庫時會被校驗。但它不是安全屬性,不能通過load方法進行賦值,解決了安全隱患。

再看rules方法按場景區(qū)分校驗器規(guī)則的做法:定義校驗器時on屬性指定規(guī)則在哪些場景下生效,except屬性則排除一些場景(如果不指定on和except,規(guī)則對所有場景生效)。例如:

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

在原來基礎(chǔ)上新增感嘆號和on/except屬性,非常簡便的就定義了非安全屬性以及分場景指定校驗規(guī)則。

scenarios

另外一種更清晰定義安全屬性和活躍屬性的做法是重寫scenarios方法。scenarios方法返回一個數(shù)組,數(shù)組的鍵是場景名稱,值是活躍屬性集合(包飯安全屬性)。例如student表的可能實現(xiàn)如下:

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

默認情形下(學生報名),年級、班級這些信息是安全屬性,但user_id不是,只能在程序內(nèi)部賦值,并在插入數(shù)據(jù)時被校驗;在修改信息時,user_id不是活躍屬性,既不能被批量賦值,也不需要校驗(事實上它不應(yīng)該改變)。

scenarios方法只能定義活躍屬性和安全屬性,無法定義校驗規(guī)則,需要和rules配合使用。

總結(jié)

金肯定義完善的數(shù)據(jù)校驗規(guī)則

業(yè)務(wù)復(fù)雜時定義多個場景,仔細為每個場景定義安全屬性和校驗規(guī)則

優(yōu)先使用rules;屬性較多、rules復(fù)雜時,可以配合scenarios方法迅速理清安全屬性和活躍屬性

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

參考

http://www.yiiframework.com/doc-2.0/guide-input-validation.html

相關(guān)文章

  • php慢查詢?nèi)罩竞湾e誤日志使用詳解

    php慢查詢?nèi)罩竞湾e誤日志使用詳解

    這篇文章主要介紹了php慢查詢?nèi)罩竞湾e誤日志使用詳解,有感興趣的可以研究下
    2021-02-02
  • dhtmlxTree目錄樹增加右鍵菜單以及拖拽排序的實現(xiàn)方法

    dhtmlxTree目錄樹增加右鍵菜單以及拖拽排序的實現(xiàn)方法

    本篇文章介紹了,dhtmlxTree目錄樹增加右鍵菜單以及拖拽排序的實現(xiàn)方法。需要的朋友參考下
    2013-04-04
  • 實例講解yii2.0在php命令行中運行的步驟

    實例講解yii2.0在php命令行中運行的步驟

    Yii中的資源是和Web頁面相關(guān)的文件,可為CSS文件,JavaScript文件,圖片或視頻等,資源放在Web可訪問的目錄下,直接被Web服務(wù)器調(diào)用。本文通過實例講解yii2.0在php命令行中運行的步驟,對yii2.0 php相關(guān)知識感興趣的朋友一起學習吧
    2015-12-12
  • 淺談Laravel中的三種中間件的作用

    淺談Laravel中的三種中間件的作用

    今天小編就為大家分享一篇淺談Laravel中的三種中間件的作用,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-10-10
  • Smarty分頁實現(xiàn)方法完整實例

    Smarty分頁實現(xiàn)方法完整實例

    這篇文章主要介紹了Smarty分頁實現(xiàn)方法,涉及基于Smarty的數(shù)據(jù)庫查詢、分頁相關(guān)計算與模板操作技巧,需要的朋友可以參考下
    2016-05-05
  • YII2框架自定義全局函數(shù)的實現(xiàn)方法小結(jié)

    YII2框架自定義全局函數(shù)的實現(xiàn)方法小結(jié)

    這篇文章主要介紹了YII2框架自定義全局函數(shù)的實現(xiàn)方法,總結(jié)分析了YII2框架自定義全局函數(shù)相關(guān)實現(xiàn)技巧與操作注意事項,需要的朋友可以參考下
    2020-03-03
  • ThinkPHP3.1新特性之查詢條件預(yù)處理簡介

    ThinkPHP3.1新特性之查詢條件預(yù)處理簡介

    相比于ThinkPHP3.0版本對數(shù)組方式的查詢條件會進行安全過濾而不支持字符串條件的安全過濾的情況,ThinkPHP3.1版本則增加了對條件字符串進行預(yù)處理的支持,讓ORM的安全性更加得以保證。這篇文章主要介紹了ThinkPHP3.1的查詢條件預(yù)處理,需要的朋友可以參考下
    2014-06-06
  • 詳解php中 === 的使用

    詳解php中 === 的使用

    很多朋友對于php中的===的使用不是很清楚,今天小編抽時間給大家介紹下php中 === 的使用,非常不錯感興趣的朋友一起學習吧
    2016-10-10
  • Laravel使用memcached緩存對文章增刪改查進行優(yōu)化的方法

    Laravel使用memcached緩存對文章增刪改查進行優(yōu)化的方法

    這篇文章主要介紹了Laravel使用memcached緩存對文章增刪改查進行優(yōu)化的方法,結(jié)合實例形式分析了Laravel框架中使用memcached緩存實現(xiàn)針對增刪改查等操作的優(yōu)化功能,需要的朋友可以參考下
    2016-10-10
  • app判斷鏈接參數(shù)后綴跳轉(zhuǎn)不同地址的方法

    app判斷鏈接參數(shù)后綴跳轉(zhuǎn)不同地址的方法

    下面小編就為大家?guī)硪黄猘pp判斷鏈接參數(shù)后綴跳轉(zhuǎn)不同地址的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09

最新評論

长治市| 汝城县| 上杭县| 肇州县| 柘荣县| 察雅县| 安龙县| 专栏| 石阡县| 德化县| 盐亭县| 房产| 五寨县| 封丘县| 宁陕县| 云龙县| 同江市| 鄂托克旗| 渝中区| 五常市| 吴江市| 青浦区| 鱼台县| 惠州市| 峨眉山市| 嵩明县| 新密市| 平凉市| 兴和县| 南康市| 宣化县| 雷山县| 福州市| 定远县| 乌拉特前旗| 隆德县| 广河县| 安顺市| 密山市| 江永县| 竹北市|