溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

PHP的Yii框架中Model模型的使用方法

發(fā)布時間:2021-09-01 21:21:31 來源:億速云 閱讀:142 作者:chen 欄目:開發(fā)技術(shù)

這篇文章主要介紹“PHP的Yii框架中Model模型的使用方法”,在日常操作中,相信很多人在PHP的Yii框架中Model模型的使用方法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”PHP的Yii框架中Model模型的使用方法”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

模型是 MVC 模式中的一部分, 是代表業(yè)務(wù)數(shù)據(jù)、規(guī)則和邏輯的對象。

模型是 CModel 或其子類的實例。模型用于保持數(shù)據(jù)以及與其相關(guān)的業(yè)務(wù)邏輯。

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

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

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

Active Record (AR) 是一種用于通過面向?qū)ο蟮娘L(fēng)格抽象化數(shù)據(jù)庫訪問的設(shè)計模式。 每個 AR 對象是一個 CActiveRecord 或其子類的實例。代表數(shù)據(jù)表中的一行。 行中的字段對應(yīng) AR 對象中的屬性。

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

  • 屬性: 代表可像普通類屬性或數(shù)組一樣被訪問的業(yè)務(wù)數(shù)據(jù);

  • 屬性標(biāo)簽: 指定屬性顯示出來的標(biāo)簽;

  • 塊賦值: 支持一步給許多屬性賦值;

  • 驗證規(guī)則: 確保輸入數(shù)據(jù)符合所申明的驗證規(guī)則;

  • 數(shù)據(jù)導(dǎo)出: 允許模型數(shù)據(jù)導(dǎo)出為自定義格式的數(shù)組。

屬性

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

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

$model = new \app\models\ContactForm;

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

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

$model = new \app\models\ContactForm;

// 像訪問數(shù)組單元項一樣訪問屬性
$model['name'] = 'example';
echo $model['name'];

// 迭代器遍歷模型
foreach ($model as $name => $value) {
  echo "$name: $value\n";
}

定義屬性

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

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 返回對應(yīng)數(shù)據(jù)表列名作為它的屬性名, 注意可能需要覆蓋魔術(shù)方法如__get(), __set()使屬性像普通對象屬性被訪問。

屬性標(biāo)簽

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

可以調(diào)用 yii\base\Model::getAttributeLabel() 獲取屬性的標(biāo)簽,例如:

$model = new \app\models\ContactForm;

// 顯示為 "Name"
echo $model->getAttributeLabel('name');

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

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

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',
    ];
  }
}

應(yīng)用支持多語言的情況下,可翻譯屬性標(biāo)簽, 可在 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'),
  ];
}

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

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

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

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

// 場景作為屬性來設(shè)置
$model = new User;
$model->scenario = 'login';

// 場景通過構(gòu)造初始化配置來設(shè)置
$model = new User(['scenario' => 'login']);

默認情況下,模型支持的場景由模型中申明的 驗證規(guī)則 來決定, 但你可以通過覆蓋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, 因為多場景的使用通常發(fā)生在Active Record 類中.
scenarios() 方法返回一個數(shù)組,數(shù)組的鍵為場景名,值為對應(yīng)的 active attributes活動屬性。 活動屬性可被 塊賦值 并遵循驗證規(guī)則在上述例子中,username 和 password 在login場景中啟用,在 register 場景中, 除了 username and password 外 email也被啟用。

scenarios() 方法默認實現(xiàn)會返回所有yii\base\Model::rules()方法申明的驗證規(guī)則中的場景, 當(dāng)覆蓋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;
  }
}

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

驗證規(guī)則

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

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

$model = new \app\models\ContactForm;

// 用戶輸入數(shù)據(jù)賦值到模型屬性
$model->attributes = \Yii::$app->request->post('ContactForm');

if ($model->validate()) {
  // 所有輸入數(shù)據(jù)都有效 all inputs are valid
} else {
  // 驗證失?。?errors 是一個包含錯誤信息的數(shù)組
  $errors = $model->errors;
}

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

public function rules()
{
  return [
    // name, email, subject 和 body 屬性必須有值
    [['name', 'email', 'subject', 'body'], 'required'],

    // email 屬性必須是一個有效的電子郵箱地址
    ['email', 'email'],
  ];
}

一條規(guī)則可用來驗證一個或多個屬性,一個屬性可對應(yīng)一條或多條規(guī)則。 更多關(guān)于如何申明驗證規(guī)則的詳情請參考 驗證輸入 一節(jié).

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

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

    // 在 "login" 場景下 username 和 password 必須有值
    [['username', 'password'], 'required', 'on' => 'login'],
  ];
}

如果沒有指定 on 屬性,規(guī)則會在所有場景下應(yīng)用, 在當(dāng)前yii\base\Model::scenario 下應(yīng)用的規(guī)則稱之為 active rule活動規(guī)則。

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

塊賦值

塊賦值只用一行代碼將用戶所有輸入填充到一個模型,非常方便, 它直接將輸入數(shù)據(jù)對應(yīng)填充到 yii\base\Model::attributes 屬性。 以下兩段代碼效果是相同的,都是將終端用戶輸入的表單數(shù)據(jù)賦值到 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;

安全屬性

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

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

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

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

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

非安全屬性

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

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

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

$model->secret = $secret;

數(shù)據(jù)導(dǎo)出

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

將模型轉(zhuǎn)換為數(shù)組最簡單的方式是使用 yii\base\Model::attributes 屬性,例如:

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

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

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

字段

字段是模型通過調(diào)用yii\base\Model::toArray()生成的數(shù)組的單元名。

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

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

// 明確列出每個字段,特別用于你想確保數(shù)據(jù)表或模型屬性改變不會導(dǎo)致你的字段改變(保證后端的API兼容).
public function fields()
{
  return [
    // 字段名和屬性名相同
    'id',

    // 字段名為 "email",對應(yīng)屬性名為 "email_address"
    'email' => 'email_address',

    // 字段名為 "name", 值通過PHP代碼返回
    'name' => function () {
      return $this->first_name . ' ' . $this->last_name;
    },
  ];
}

// 過濾掉一些字段,特別用于你想繼承父類實現(xiàn)并不想用一些敏感字段
public function fields()
{
  $fields = parent::fields();

  // 去掉一些包含敏感信息的字段
  unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']);

  return $fields;
}

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

到此,關(guān)于“PHP的Yii框架中Model模型的使用方法”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI