亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > PHP > 正文

PHP的Yii框架中Model模型的學習教程

2024-05-04 23:44:29
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了PHP的Yii框架中Model模型的學習教程,Yii框架本身就顯龐大,所以模型類也就更加需要很好的編寫維護,需要的朋友可以參考下
 

模型是 MVC 模式中的一部分, 是代表業務數據、規則和邏輯的對象。

模型是 CModel 或其子類的實例。模型用于保持數據以及與其相關的業務邏輯。

模型是單獨的數據對象。它可以是數據表中的一行,或者一個用戶輸入的表單。 數據對象的每個字段對應模型中的一個屬性。每個屬性有一個標簽(label), 并且可以通過一系列規則進行驗證。

Yii 實現了兩種類型的模型:表單模型和 Active Record。二者均繼承于相同的基類 CModel。

表單模型是 CFormModel 的實例。表單模型用于保持從用戶的輸入獲取的數據。 這些數據經常被獲取,使用,然后丟棄。例如,在一個登錄頁面中, 我們可以使用表單模型用于表示由最終用戶提供的用戶名和密碼信息。

Active Record (AR) 是一種用于通過面向對象的風格抽象化數據庫訪問的設計模式。 每個 AR 對象是一個 CActiveRecord 或其子類的實例。代表數據表中的一行。 行中的字段對應 AR 對象中的屬性。

可通過繼承 yii/base/Model 或它的子類定義模型類,基類yii/base/Model支持許多實用的特性:

  • 屬性: 代表可像普通類屬性或數組一樣被訪問的業務數據;
  • 屬性標簽: 指定屬性顯示出來的標簽;
  • 塊賦值: 支持一步給許多屬性賦值;
  • 驗證規則: 確保輸入數據符合所申明的驗證規則;
  • 數據導出: 允許模型數據導出為自定義格式的數組。

屬性

模型通過 屬性 來代表業務數據,每個屬性像是模型的公有可訪問屬性, yii/base/Model::attributes() 指定模型所擁有的屬性。

可像訪問一個對象屬性一樣訪問模型的屬性:

$model = new /app/models/ContactForm;// "name" 是ContactForm模型的屬性$model->name = 'example';echo $model->name;

也可像訪問數組單元項一樣訪問屬性,這要感謝yii/base/Model支持 ArrayAccess 數組訪問 和 ArrayIterator 數組迭代器:

$model = new /app/models/ContactForm;// 像訪問數組單元項一樣訪問屬性$model['name'] = 'example';echo $model['name'];// 迭代器遍歷模型foreach ($model as $name => $value) {  echo "$name: $value/n";}

定義屬性

默認情況下你的模型類直接從yii/base/Model繼承,所有 non-static public非靜態公有 成員變量都是屬性。 例如,下述ContactForm模型類有四個屬性name, email, subject and body, ContactForm 模型用來代表從HTML表單獲取的輸入數據。

namespace app/models;use yii/base/Model;class ContactForm extends Model{  public $name;  public $email;  public $subject;  public $body;}

另一種方式是可覆蓋 yii/base/Model::attributes() 來定義屬性,該方法返回模型的屬性名。 例如 yii/db/ActiveRecord 返回對應數據表列名作為它的屬性名, 注意可能需要覆蓋魔術方法如__get(), __set()使屬性像普通對象屬性被訪問。

屬性標簽

當屬性顯示或獲取輸入時,經常要顯示屬性相關標簽,例如假定一個屬性名為firstName, 在某些地方如表單輸入或錯誤信息處,你可能想顯示對終端用戶來說更友好的 First Name 標簽。

可以調用 yii/base/Model::getAttributeLabel() 獲取屬性的標簽,例如:

$model = new /app/models/ContactForm;// 顯示為 "Name"echo $model->getAttributeLabel('name');

默認情況下,屬性標簽通過yii/base/Model::generateAttributeLabel()方法自動從屬性名生成. 它會自動將駝峰式大小寫變量名轉換為多個首字母大寫的單詞,例如 username 轉換為 Username, firstName 轉換為 First Name。

如果你不想用自動生成的標簽,可以覆蓋 yii/base/Model::attributeLabels() 方法明確指定屬性標簽,例如:

namespace app/models;use yii/base/Model;class ContactForm extends Model{  public $name;  public $email;  public $subject;  public $body;  public function attributeLabels()  {    return [      'name' => 'Your name',      'email' => 'Your email address',      'subject' => 'Subject',      'body' => 'Content',    ];  }}

應用支持多語言的情況下,可翻譯屬性標簽, 可在 yii/base/Model::attributeLabels() 方法中定義,如下所示:

public function attributeLabels(){  return [    'name' => /Yii::t('app', 'Your name'),    'email' => /Yii::t('app', 'Your email address'),    'subject' => /Yii::t('app', 'Subject'),    'body' => /Yii::t('app', 'Content'),  ];}

甚至可以根據條件定義標簽,例如通過使用模型的 scenario場景, 可對相同的屬性返回不同的標簽。

補充:屬性標簽是 視圖一部分,但是在模型中申明標簽通常非常方便,并可行程非常簡潔可重用代碼。
場景

模型可能在多個 場景 下使用,例如 User 模塊可能會在收集用戶登錄輸入,也可能會在用戶注冊時使用。 在不同的場景下,模型可能會使用不同的業務規則和邏輯,例如 email 屬性在注冊時強制要求有,但在登陸時不需要。

模型使用 yii/base/Model::scenario 屬性保持使用場景的跟蹤, 默認情況下,模型支持一個名為 default 的場景,如下展示兩種設置場景的方法:

// 場景作為屬性來設置$model = new User;$model->scenario = 'login';// 場景通過構造初始化配置來設置$model = new User(['scenario' => 'login']);

默認情況下,模型支持的場景由模型中申明的 驗證規則 來決定, 但你可以通過覆蓋yii/base/Model::scenarios()方法來自定義行為,如下所示:

namespace app/models;use yii/db/ActiveRecord;class User extends ActiveRecord{  public function scenarios()  {    return [      'login' => ['username', 'password'],      'register' => ['username', 'email', 'password'],    ];  }}

補充:在上述和下述的例子中,模型類都是繼承yii/db/ActiveRecord, 因為多場景的使用通常發生在Active Record 類中.
scenarios() 方法返回一個數組,數組的鍵為場景名,值為對應的 active attributes活動屬性。 活動屬性可被 塊賦值 并遵循驗證規則在上述例子中,username 和 password 在login場景中啟用,在 register 場景中, 除了 username and password 外 email也被啟用。

scenarios() 方法默認實現會返回所有yii/base/Model::rules()方法申明的驗證規則中的場景, 當覆蓋scenarios()時,如果你想在默認場景外使用新場景,可以編寫類似如下代碼:

namespace app/models;use yii/db/ActiveRecord;class User extends ActiveRecord{  public function scenarios()  {    $scenarios = parent::scenarios();    $scenarios['login'] = ['username', 'password'];    $scenarios['register'] = ['username', 'email', 'password'];    return $scenarios;  }}

場景特性主要在驗證 和 屬性塊賦值 中使用。 你也可以用于其他目的,例如可基于不同的場景定義不同的 屬性標簽。

驗證規則

當模型接收到終端用戶輸入的數據,數據應當滿足某種規則(稱為 驗證規則, 也稱為 業務規則)。 例如假定ContactForm模型,你可能想確保所有屬性不為空且 email 屬性包含一個有效的郵箱地址, 如果某個屬性的值不滿足對應的業務規則,相應的錯誤信息應顯示,以幫助用戶修正錯誤。

可調用 yii/base/Model::validate() 來驗證接收到的數據, 該方法使用yii/base/Model::rules()申明的驗證規則來驗證每個相關屬性, 如果沒有找到錯誤,會返回 true,否則它會將錯誤保存在 yii/base/Model::errors 屬性中并返回false,例如:

$model = new /app/models/ContactForm;// 用戶輸入數據賦值到模型屬性$model->attributes = /Yii::$app->request->post('ContactForm');if ($model->validate()) {  // 所有輸入數據都有效 all inputs are valid} else {  // 驗證失?。?errors 是一個包含錯誤信息的數組  $errors = $model->errors;}

通過覆蓋 yii/base/Model::rules() 方法指定模型屬性應該滿足的規則來申明模型相關驗證規則。 下述例子顯示ContactForm模型申明的驗證規則:

public function rules(){  return [    // name, email, subject 和 body 屬性必須有值    [['name', 'email', 'subject', 'body'], 'required'],    // email 屬性必須是一個有效的電子郵箱地址    ['email', 'email'],  ];}

一條規則可用來驗證一個或多個屬性,一個屬性可對應一條或多條規則。 更多關于如何申明驗證規則的詳情請參考 驗證輸入 一節.

有時你想一條規則只在某個 場景 下應用,為此你可以指定規則的 on 屬性,如下所示:

public function rules(){  return [    // 在"register" 場景下 username, email 和 password 必須有值    [['username', 'email', 'password'], 'required', 'on' => 'register'],    // 在 "login" 場景下 username 和 password 必須有值    [['username', 'password'], 'required', 'on' => 'login'],  ];}

如果沒有指定 on 屬性,規則會在所有場景下應用, 在當前yii/base/Model::scenario 下應用的規則稱之為 active rule活動規則。

一個屬性只會屬于scenarios()中定義的活動屬性且在rules()申明對應一條或多條活動規則的情況下被驗證。

塊賦值

塊賦值只用一行代碼將用戶所有輸入填充到一個模型,非常方便, 它直接將輸入數據對應填充到 yii/base/Model::attributes 屬性。 以下兩段代碼效果是相同的,都是將終端用戶輸入的表單數據賦值到 ContactForm 模型的屬性, 明顯地前一段塊賦值的代碼比后一段代碼簡潔且不易出錯。

$model = new /app/models/ContactForm;$model->attributes = /Yii::$app->request->post('ContactForm');$model = new /app/models/ContactForm;$data = /Yii::$app->request->post('ContactForm', []);$model->name = isset($data['name']) ? $data['name'] : null;$model->email = isset($data['email']) ? $data['email'] : null;$model->subject = isset($data['subject']) ? $data['subject'] : null;$model->body = isset($data['body']) ? $data['body'] : null;

安全屬性

塊賦值只應用在模型當前yii/base/Model::scenario場景yii/base/Model::scenarios()方法 列出的稱之為 安全屬性 的屬性上,例如,如果User模型申明以下場景, 當當前場景為login時候,只有username and password 可被塊賦值,其他屬性不會被賦值。

public function scenarios(){  return [    'login' => ['username', 'password'],    'register' => ['username', 'email', 'password'],  ];}

補充: 塊賦值只應用在安全屬性上,因為你想控制哪些屬性會被終端用戶輸入數據所修改, 例如,如果 User 模型有一個permission屬性對應用戶的權限, 你可能只想讓這個屬性在后臺界面被管理員修改。
由于默認yii/base/Model::scenarios()的實現會返回yii/base/Model::rules()所有屬性和數據, 如果不覆蓋這個方法,表示所有只要出現在活動驗證規則中的屬性都是安全的。

為此,提供一個特別的別名為 safe 的驗證器來申明哪些屬性是安全的不需要被驗證, 如下示例的規則申明 title 和 description都為安全屬性。

public function rules(){  return [    [['title', 'description'], 'safe'],  ];}

非安全屬性

如上所述,yii/base/Model::scenarios() 方法提供兩個用處:定義哪些屬性應被驗證,定義哪些屬性安全。 在某些情況下,你可能想驗證一個屬性但不想讓他是安全的,可在scenarios()方法中屬性名加一個驚嘆號 !。 例如像如下的secret屬性。

public function scenarios(){  return [    'login' => ['username', 'password', '!secret'],  ];}

當模型在 login 場景下,三個屬性都會被驗證,但只有 username和 password 屬性會被塊賦值, 要對secret屬性賦值,必須像如下例子明確對它賦值。

$model->secret = $secret;

數據導出

模型通常要導出成不同格式,例如,你可能想將模型的一個集合轉成JSON或Excel格式, 導出過程可分解為兩個步驟,第一步,模型轉換成數組;第二步,數組轉換成所需要的格式。 你只需要關注第一步,因為第二步可被通用的數據轉換器如yii/web/JsonResponseFormatter來完成。

將模型轉換為數組最簡單的方式是使用 yii/base/Model::attributes 屬性,例如:

$post = /app/models/Post::findOne(100);$array = $post->attributes;

yii/base/Model::attributes 屬性會返回 所有 yii/base/Model::attributes() 申明的屬性的值。

更靈活和強大的將模型轉換為數組的方式是使用 yii/base/Model::toArray() 方法, 它的行為默認和 yii/base/Model::attributes 相同, 但是它允許你選擇哪些稱之為字段的數據項放入到結果數組中并同時被格式化。 實際上,它是導出模型到 RESTful 網頁服務開發的默認方法,詳情請參閱響應格式.

字段

字段是模型通過調用yii/base/Model::toArray()生成的數組的單元名。

默認情況下,字段名對應屬性名,但是你可以通過覆蓋 yii/base/Model::fields() 和/或 yii/base/Model::extraFields() 方法來改變這種行為, 兩個方法都返回一個字段定義列表,fields() 方法定義的字段是默認字段,表示toArray()方法默認會返回這些字段。extraFields()方法定義額外可用字段,通過toArray()方法指定$expand參數來返回這些額外可用字段。 例如如下代碼會返回fields()方法定義的所有字段和extraFields()方法定義的prettyName and fullAddress字段。

$array = $model->toArray([], ['prettyName', 'fullAddress']);
可通過覆蓋 fields() 來增加、刪除、重命名和重定義字段,fields() 方法返回值應為數組, 數組的鍵為字段名,數組的值為對應的可為屬性名或匿名函數返回的字段定義對應的值。 特使情況下,如果字段名和屬性定義名相同,可以省略數組鍵,例如:

// 明確列出每個字段,特別用于你想確保數據表或模型屬性改變不會導致你的字段改變(保證后端的API兼容).public function fields(){  return [    // 字段名和屬性名相同    'id',    // 字段名為 "email",對應屬性名為 "email_address"    'email' => 'email_address',    // 字段名為 "name", 值通過PHP代碼返回    'name' => function () {      return $this->first_name . ' ' . $this->last_name;    },  ];}// 過濾掉一些字段,特別用于你想繼承父類實現并不想用一些敏感字段public function fields(){  $fields = parent::fields();  // 去掉一些包含敏感信息的字段  unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']);  return $fields;}

警告:由于模型的所有屬性會被包含在導出數組,最好檢查數據確保沒包含敏感數據, 如果有敏感數據,應覆蓋 fields() 方法過濾掉,在上述列子中,我們選擇過濾掉 auth_key, password_hash and password_reset_token。
最佳實踐

模型是代表業務數據、規則和邏輯的中心地方,通常在很多地方重用, 在一個設計良好的應用中,模型通常比控制器代碼多。

歸納起來,模型:

  • 可包含屬性來展示業務數據;
  • 可包含驗證規則確保數據有效和完整;
  • 可包含方法實現業務邏輯;
  • 不應直接訪問請求,session和其他環境數據,這些數據應該由控制器傳入到模型;
  • 應避免嵌入HTML或其他展示代碼,這些代碼最好在 視圖中處理;
  • 單個模型中避免太多的場景.

在開發大型復雜系統時應經常考慮最后一條建議, 在這些系統中,模型會很大并在很多地方使用,因此會包含需要規則集和業務邏輯, 最后維護這些模型代碼成為一個噩夢,因為一個簡單修改會影響好多地方, 為確保模型好維護,最好使用以下策略:

定義可被多個 應用主體 或 模塊 共享的模型基類集合。 這些模型類應包含通用的最小規則集合和邏輯。
在每個使用模型的 應用主體 或 模塊中, 通過繼承對應的模型基類來定義具體的模型類,具體模型類包含應用主體或模塊指定的規則和邏輯。
例如,在高級應用模板,你可以定義一個模型基類common/models/Post, 然后在前臺應用中,定義并使用一個繼承common/models/Post的具體模型類frontend/models/Post, 在后臺應用中可以類似地定義backend/models/Post。 通過這種策略,你清楚frontend/models/Post只對應前臺應用,如果你修改它,就無需擔憂修改會影響后臺應用。



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美成人一区二区三区电影| 国产99久久精品一区二区| 国产精品青草久久久久福利99| 9.1国产丝袜在线观看| 亚洲视频自拍偷拍| 日韩在线一区二区三区免费视频| 日韩av理论片| 亚洲国产小视频在线观看| 欧美电影免费观看高清完整| 亚洲精品国产suv| 国产精品爽爽爽爽爽爽在线观看| 国产成人亚洲综合91精品| 久久久久久久久国产| 日韩精品在线免费播放| 亚洲精品国产精品国自产观看浪潮| 欧美色道久久88综合亚洲精品| 国内免费久久久久久久久久久| 日韩欧美精品网站| 亚洲色图第一页| 国产精品成av人在线视午夜片| 日韩性xxxx爱| 久久久久久久久久亚洲| 国产精品免费在线免费| 亚洲色图av在线| 亚洲男人的天堂网站| 性欧美xxxx视频在线观看| 亚洲性69xxxbbb| 久久久极品av| 久久久www成人免费精品张筱雨| 欧美国产中文字幕| 久久男人av资源网站| 九九热99久久久国产盗摄| 国产+成+人+亚洲欧洲| 亚州成人av在线| 欧美xxxx14xxxxx性爽| 国产成人精品久久二区二区| 日韩av在线免费| 色系列之999| 青青草原成人在线视频| 在线观看日韩专区| 国产97在线观看| 最近2019年中文视频免费在线观看| 欧美另类在线观看| 日日骚久久av| 日韩一区二区三区在线播放| 欧美极品第一页| 亚洲欧美日韩精品久久| 8x海外华人永久免费日韩内陆视频| 国产精品国产三级国产aⅴ9色| 亚洲自拍偷拍色片视频| 国产69精品99久久久久久宅男| 久久在线观看视频| 欧美麻豆久久久久久中文| 国产91对白在线播放| 精品久久久久久久久久久| 在线观看日韩www视频免费| 亚洲精品视频网上网址在线观看| 国产精品极品美女在线观看免费| 亚洲精品国产欧美| 综合136福利视频在线| 日韩中文字幕欧美| 欧美激情二区三区| 日本精品久久久久影院| 国产日产欧美精品| 精品久久久一区| 日韩在线观看免费全| 97国产真实伦对白精彩视频8| 狠狠躁夜夜躁人人爽超碰91| 国产亚洲精品久久久久久777| 国产69精品久久久久9| 亚洲精品第一国产综合精品| 亚洲激情在线视频| 欧美自拍视频在线观看| 国产精品色悠悠| 欧美专区中文字幕| 欧美精品激情在线观看| 日韩成人中文电影| 欧美日韩在线视频首页| 国产精品欧美亚洲777777| 91热福利电影| 日本一区二三区好的精华液| 久久精品中文字幕一区| 欧美wwwwww| 日韩精品999| 亚洲国产精品嫩草影院久久| 亚洲一品av免费观看| 色哟哟入口国产精品| 国语自产精品视频在线看一大j8| 欧美孕妇孕交黑巨大网站| 久久国产精品99国产精| 亚洲国产精品久久久久| 97香蕉久久夜色精品国产| 日韩av中文字幕在线| 91亚洲人电影| 成人激情av在线| 亚洲xxxx18| 亚洲欧美日韩国产中文| 精品无人区乱码1区2区3区在线| 国产午夜精品视频免费不卡69堂| 色噜噜狠狠狠综合曰曰曰88av| 亚洲国产古装精品网站| 久久久久久亚洲精品不卡| 精品国产电影一区| 亚洲激情在线视频| 国产精品亚洲精品| 亚洲欧洲中文天堂| 亚洲精品永久免费精品| 91沈先生作品| 精品一区精品二区| 欧美激情18p| 国产精品成人在线| 亚洲欧美激情另类校园| 亚洲综合成人婷婷小说| 最近的2019中文字幕免费一页| 伊人久久久久久久久久| 成人h视频在线观看播放| 亚洲第一区第二区| 午夜精品久久久久久久99热浪潮| 日韩精品免费一线在线观看| 亚洲国产欧美一区二区丝袜黑人| 91精品免费久久久久久久久| 在线视频免费一区二区| 92国产精品久久久久首页| 国产成人精品视频在线观看| 26uuu另类亚洲欧美日本老年| 国产精品高精视频免费| 亚洲欧美国产精品久久久久久久| 这里只有精品视频在线| 亚洲sss综合天堂久久| 日韩国产高清污视频在线观看| 91久久精品日日躁夜夜躁国产| 91成品人片a无限观看| 日本三级韩国三级久久| 色无极影院亚洲| 国产精品第七影院| 国产精品久久久久久久久免费| 91综合免费在线| 亚洲欧美日韩天堂一区二区| 欧美成年人网站| 国内精久久久久久久久久人| 国产欧美日韩最新| 精品久久香蕉国产线看观看gif| 国产一区二区三区视频在线观看| 日韩国产高清视频在线| 国产精品久久久久久av福利| 欧美日韩在线视频一区| 日韩精品极品毛片系列视频| 日韩av男人的天堂| 一个人看的www欧美| 国产中文欧美精品| 国产精品福利无圣光在线一区| 亚洲va男人天堂| 欧美大片在线看免费观看| 欧美国产高跟鞋裸体秀xxxhd| 久久久日本电影| 尤物99国产成人精品视频| 九九热这里只有精品6| 91精品视频免费看| 亚洲精品网站在线播放gif| 久久精品中文字幕免费mv| 欧美电影免费观看大全| 欧美日本啪啪无遮挡网站| 日韩av高清不卡| 日韩av在线影院|