


Learning tutorial for Model model in PHP's Yii framework, yiimodel_PHP tutorial
Jul 12, 2016 am 08:55 AMA learning tutorial for the Model model in PHP's Yii framework. The yiimodel
model is part of the MVC pattern and is an object that represents business data, rules and logic.
A model is an instance of CModel or its subclass. Models are used to hold data and the business logic associated with it.
Models are separate data objects. It can be a row in a data table, or a user-entered form. Each field of the data object corresponds to an attribute in the model. Each attribute has a label and can be verified through a series of rules.
Yii implements two types of models: form model and Active Record. Both inherit from the same base class CModel.
Form models are instances of CFormModel. The form model is used to hold data obtained from the user's input. This data is often acquired, used, and then discarded. For example, in a login page, we can use the form model to represent the username and password information provided by the end user.
Active Record (AR) is a design pattern for abstracting database access in an object-oriented style. Each AR object is an instance of CActiveRecord or one of its subclasses. Represents a row in the data table. The fields in the row correspond to properties in the AR object.
Model classes can be defined by inheriting yiibaseModel or its subclasses. The base class yiibaseModel supports many practical features:
- Attribute: Represents business data that can be accessed like a normal class attribute or array;
- Attribute label: The label displayed by the specified attribute;
- Block assignment: supports assigning values ??to many attributes in one step;
- Validation rules: Ensure that the input data conforms to the declared validation rules;
- Data export: Allows model data to be exported as an array in a custom format.
Attributes
The model represents business data through attributes. Each attribute is like a publicly accessible attribute of the model. yiibaseModel::attributes() specifies the attributes owned by the model.
A model's properties can be accessed just like an object's properties:
$model = new \app\models\ContactForm; // "name" 是ContactForm模型的屬性 $model->name = 'example'; echo $model->name;
Properties can also be accessed like array cell items, thanks to yiibaseModel's support for ArrayAccess and ArrayIterator array iterators:
$model = new \app\models\ContactForm; // 像訪問(wèn)數(shù)組單元項(xiàng)一樣訪問(wèn)屬性 $model['name'] = 'example'; echo $model['name']; // 迭代器遍歷模型 foreach ($model as $name => $value) { echo "$name: $value\n"; }
Define attributes
By default, your model class inherits directly from yiibaseModel, and all non-static public non-static public member variables are properties. For example, the following ContactForm model class has four attributes name, email, subject and body. The ContactForm model is used to represent input data obtained from an HTML form.
namespace app\models; use yii\base\Model; class ContactForm extends Model { public $name; public $email; public $subject; public $body; }
Another way is to override yiibaseModel::attributes() to define attributes. This method returns the attribute name of the model. For example, yiidbActiveRecord returns the corresponding data table column name as its attribute name. Note that you may need to override magic methods such as __get(), __set() to make the attributes be accessed like ordinary object attributes.
Attribute tag
When an attribute is displayed or input is obtained, it is often necessary to display attribute-related labels. For example, assuming an attribute is named firstName, in some places such as form input or error messages, you may want to display a label that is more friendly to the end user. First Name tag.
You can call yiibaseModel::getAttributeLabel() to get the label of the attribute, for example:
$model = new \app\models\ContactForm; // 顯示為 "Name" echo $model->getAttributeLabel('name');
By default, attribute labels are automatically generated from attribute names through the yiibaseModel::generateAttributeLabel() method. It will automatically convert camel case variable names into multiple words with the first letter capitalized, for example, username is converted to Username, firstName Convert to First Name.
If you don’t want to use automatically generated labels, you can override the yiibaseModel::attributeLabels() method to specify attribute labels explicitly, for example:
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', ]; } }
When the application supports multiple languages, the attribute labels can be translated and can be defined in the yiibaseModel::attributeLabels() method, as shown below:
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'), ]; }
You can even define labels based on conditions, such as by using a model's scenario to return different labels for the same property.
Supplement: Attribute labels are part of the view, but declaring labels in the model is usually very convenient and can lead to very concise and reusable code.
Scene
The model may be used in multiple scenarios. For example, the User module may collect user login input or may be used when the user registers. In different scenarios, the model may use different business rules and logic. For example, the email attribute is mandatory during registration, but not required during login.
The model uses the yiibaseModel::scenario attribute to keep track of usage scenarios. By default, the model supports a scenario named default. Two methods of setting the scenario are shown below:
// 場(chǎng)景作為屬性來(lái)設(shè)置 $model = new User; $model->scenario = 'login'; // 場(chǎng)景通過(guò)構(gòu)造初始化配置來(lái)設(shè)置 $model = new User(['scenario' => 'login']);
By default, the scenarios supported by the model are determined by the validation rules declared in the model, but you can customize the behavior by overriding the yiibaseModel::scenarios() method, as shown below:
namespace app\models; use yii\db\ActiveRecord; class User extends ActiveRecord { public function scenarios() { return [ 'login' => ['username', 'password'], 'register' => ['username', 'email', 'password'], ]; } }
補(bǔ)充:在上述和下述的例子中,模型類都是繼承yii\db\ActiveRecord, 因?yàn)槎鄨?chǎng)景的使用通常發(fā)生在Active Record 類中.
scenarios() 方法返回一個(gè)數(shù)組,數(shù)組的鍵為場(chǎng)景名,值為對(duì)應(yīng)的 active attributes活動(dòng)屬性。 活動(dòng)屬性可被 塊賦值 并遵循驗(yàn)證規(guī)則在上述例子中,username 和 password 在login場(chǎng)景中啟用,在 register 場(chǎng)景中, 除了 username and password 外 email也被啟用。
scenarios() 方法默認(rèn)實(shí)現(xiàn)會(huì)返回所有yii\base\Model::rules()方法申明的驗(yàn)證規(guī)則中的場(chǎng)景, 當(dāng)覆蓋scenarios()時(shí),如果你想在默認(rèn)場(chǎng)景外使用新場(chǎng)景,可以編寫(xiě)類似如下代碼:
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; } }
場(chǎng)景特性主要在驗(yàn)證 和 屬性塊賦值 中使用。 你也可以用于其他目的,例如可基于不同的場(chǎng)景定義不同的 屬性標(biāo)簽。
驗(yàn)證規(guī)則
當(dāng)模型接收到終端用戶輸入的數(shù)據(jù),數(shù)據(jù)應(yīng)當(dāng)滿足某種規(guī)則(稱為 驗(yàn)證規(guī)則, 也稱為 業(yè)務(wù)規(guī)則)。 例如假定ContactForm模型,你可能想確保所有屬性不為空且 email 屬性包含一個(gè)有效的郵箱地址, 如果某個(gè)屬性的值不滿足對(duì)應(yīng)的業(yè)務(wù)規(guī)則,相應(yīng)的錯(cuò)誤信息應(yīng)顯示,以幫助用戶修正錯(cuò)誤。
可調(diào)用 yii\base\Model::validate() 來(lái)驗(yàn)證接收到的數(shù)據(jù), 該方法使用yii\base\Model::rules()申明的驗(yàn)證規(guī)則來(lái)驗(yàn)證每個(gè)相關(guān)屬性, 如果沒(méi)有找到錯(cuò)誤,會(huì)返回 true,否則它會(huì)將錯(cuò)誤保存在 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 { // 驗(yàn)證失?。?errors 是一個(gè)包含錯(cuò)誤信息的數(shù)組 $errors = $model->errors; }
通過(guò)覆蓋 yii\base\Model::rules() 方法指定模型屬性應(yīng)該滿足的規(guī)則來(lái)申明模型相關(guān)驗(yàn)證規(guī)則。 下述例子顯示ContactForm模型申明的驗(yàn)證規(guī)則:
public function rules() { return [ // name, email, subject 和 body 屬性必須有值 [['name', 'email', 'subject', 'body'], 'required'], // email 屬性必須是一個(gè)有效的電子郵箱地址 ['email', 'email'], ]; }
一條規(guī)則可用來(lái)驗(yàn)證一個(gè)或多個(gè)屬性,一個(gè)屬性可對(duì)應(yīng)一條或多條規(guī)則。 更多關(guān)于如何申明驗(yàn)證規(guī)則的詳情請(qǐng)參考 驗(yàn)證輸入 一節(jié).
有時(shí)你想一條規(guī)則只在某個(gè) 場(chǎng)景 下應(yīng)用,為此你可以指定規(guī)則的 on 屬性,如下所示:
public function rules() { return [ // 在"register" 場(chǎng)景下 username, email 和 password 必須有值 [['username', 'email', 'password'], 'required', 'on' => 'register'], // 在 "login" 場(chǎng)景下 username 和 password 必須有值 [['username', 'password'], 'required', 'on' => 'login'], ]; }
如果沒(méi)有指定 on 屬性,規(guī)則會(huì)在所有場(chǎng)景下應(yīng)用, 在當(dāng)前yii\base\Model::scenario 下應(yīng)用的規(guī)則稱之為 active rule活動(dòng)規(guī)則。
一個(gè)屬性只會(huì)屬于scenarios()中定義的活動(dòng)屬性且在rules()申明對(duì)應(yīng)一條或多條活動(dòng)規(guī)則的情況下被驗(yàn)證。
塊賦值
塊賦值只用一行代碼將用戶所有輸入填充到一個(gè)模型,非常方便, 它直接將輸入數(shù)據(jù)對(duì)應(yīng)填充到 yii\base\Model::attributes 屬性。 以下兩段代碼效果是相同的,都是將終端用戶輸入的表單數(shù)據(jù)賦值到 ContactForm 模型的屬性, 明顯地前一段塊賦值的代碼比后一段代碼簡(jiǎn)潔且不易出錯(cuò)。
$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場(chǎng)景yii\base\Model::scenarios()方法 列出的稱之為 安全屬性 的屬性上,例如,如果User模型申明以下場(chǎng)景, 當(dāng)當(dāng)前場(chǎng)景為login時(shí)候,只有username and password 可被塊賦值,其他屬性不會(huì)被賦值。
public function scenarios() { return [ 'login' => ['username', 'password'], 'register' => ['username', 'email', 'password'], ]; }
補(bǔ)充: 塊賦值只應(yīng)用在安全屬性上,因?yàn)槟阆肟刂颇男傩詴?huì)被終端用戶輸入數(shù)據(jù)所修改, 例如,如果 User 模型有一個(gè)permission屬性對(duì)應(yīng)用戶的權(quán)限, 你可能只想讓這個(gè)屬性在后臺(tái)界面被管理員修改。
由于默認(rèn)yii\base\Model::scenarios()的實(shí)現(xiàn)會(huì)返回yii\base\Model::rules()所有屬性和數(shù)據(jù), 如果不覆蓋這個(gè)方法,表示所有只要出現(xiàn)在活動(dòng)驗(yàn)證規(guī)則中的屬性都是安全的。
為此,提供一個(gè)特別的別名為 safe 的驗(yàn)證器來(lái)申明哪些屬性是安全的不需要被驗(yàn)證, 如下示例的規(guī)則申明 title 和 description都為安全屬性。
public function rules() { return [ [['title', 'description'], 'safe'], ]; }
非安全屬性
如上所述,yii\base\Model::scenarios() 方法提供兩個(gè)用處:定義哪些屬性應(yīng)被驗(yàn)證,定義哪些屬性安全。 在某些情況下,你可能想驗(yàn)證一個(gè)屬性但不想讓他是安全的,可在scenarios()方法中屬性名加一個(gè)驚嘆號(hào) !。 例如像如下的secret屬性。
public function scenarios() { return [ 'login' => ['username', 'password', '!secret'], ]; }
當(dāng)模型在 login 場(chǎng)景下,三個(gè)屬性都會(huì)被驗(yàn)證,但只有 username和 password 屬性會(huì)被塊賦值, 要對(duì)secret屬性賦值,必須像如下例子明確對(duì)它賦值。
$model->secret = $secret;
數(shù)據(jù)導(dǎo)出
模型通常要導(dǎo)出成不同格式,例如,你可能想將模型的一個(gè)集合轉(zhuǎn)成JSON或Excel格式, 導(dǎo)出過(guò)程可分解為兩個(gè)步驟,第一步,模型轉(zhuǎn)換成數(shù)組;第二步,數(shù)組轉(zhuǎn)換成所需要的格式。 你只需要關(guān)注第一步,因?yàn)榈诙娇杀煌ㄓ玫臄?shù)據(jù)轉(zhuǎn)換器如yii\web\JsonResponseFormatter來(lái)完成。
將模型轉(zhuǎn)換為數(shù)組最簡(jiǎn)單的方式是使用 yii\base\Model::attributes 屬性,例如:
$post = \app\models\Post::findOne(100); $array = $post->attributes;
yii\base\Model::attributes 屬性會(huì)返回 所有 yii\base\Model::attributes() 申明的屬性的值。
更靈活和強(qiáng)大的將模型轉(zhuǎn)換為數(shù)組的方式是使用 yii\base\Model::toArray() 方法, 它的行為默認(rèn)和 yii\base\Model::attributes 相同, 但是它允許你選擇哪些稱之為字段的數(shù)據(jù)項(xiàng)放入到結(jié)果數(shù)組中并同時(shí)被格式化。 實(shí)際上,它是導(dǎo)出模型到 RESTful 網(wǎng)頁(yè)服務(wù)開(kāi)發(fā)的默認(rèn)方法,詳情請(qǐng)參閱響應(yīng)格式.
字段
字段是模型通過(guò)調(diào)用yii\base\Model::toArray()生成的數(shù)組的單元名。
默認(rèn)情況下,字段名對(duì)應(yīng)屬性名,但是你可以通過(guò)覆蓋 yii\base\Model::fields() 和/或 yii\base\Model::extraFields() 方法來(lái)改變這種行為, 兩個(gè)方法都返回一個(gè)字段定義列表,fields() 方法定義的字段是默認(rèn)字段,表示toArray()方法默認(rèn)會(huì)返回這些字段。extraFields()方法定義額外可用字段,通過(guò)toArray()方法指定$expand參數(shù)來(lái)返回這些額外可用字段。 例如如下代碼會(huì)返回fields()方法定義的所有字段和extraFields()方法定義的prettyName and fullAddress字段。
$array = $model->toArray([], ['prettyName', 'fullAddress']);
可通過(guò)覆蓋 fields() 來(lái)增加、刪除、重命名和重定義字段,fields() 方法返回值應(yīng)為數(shù)組, 數(shù)組的鍵為字段名,數(shù)組的值為對(duì)應(yīng)的可為屬性名或匿名函數(shù)返回的字段定義對(duì)應(yīng)的值。 特使情況下,如果字段名和屬性定義名相同,可以省略數(shù)組鍵,例如:
// 明確列出每個(gè)字段,特別用于你想確保數(shù)據(jù)表或模型屬性改變不會(huì)導(dǎo)致你的字段改變(保證后端的API兼容). public function fields() { return [ // 字段名和屬性名相同 'id', // 字段名為 "email",對(duì)應(yīng)屬性名為 "email_address" 'email' => 'email_address', // 字段名為 "name", 值通過(guò)PHP代碼返回 'name' => function () { return $this->first_name . ' ' . $this->last_name; }, ]; } // 過(guò)濾掉一些字段,特別用于你想繼承父類實(shí)現(xiàn)并不想用一些敏感字段 public function fields() { $fields = parent::fields(); // 去掉一些包含敏感信息的字段 unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']); return $fields; }
警告:由于模型的所有屬性會(huì)被包含在導(dǎo)出數(shù)組,最好檢查數(shù)據(jù)確保沒(méi)包含敏感數(shù)據(jù), 如果有敏感數(shù)據(jù),應(yīng)覆蓋 fields() 方法過(guò)濾掉,在上述列子中,我們選擇過(guò)濾掉 auth_key, password_hash and password_reset_token。
最佳實(shí)踐
模型是代表業(yè)務(wù)數(shù)據(jù)、規(guī)則和邏輯的中心地方,通常在很多地方重用, 在一個(gè)設(shè)計(jì)良好的應(yīng)用中,模型通常比控制器代碼多。
歸納起來(lái),模型:
- 可包含屬性來(lái)展示業(yè)務(wù)數(shù)據(jù);
- 可包含驗(yàn)證規(guī)則確保數(shù)據(jù)有效和完整;
- 可包含方法實(shí)現(xiàn)業(yè)務(wù)邏輯;
- 不應(yīng)直接訪問(wèn)請(qǐng)求,session和其他環(huán)境數(shù)據(jù),這些數(shù)據(jù)應(yīng)該由控制器傳入到模型;
- 應(yīng)避免嵌入HTML或其他展示代碼,這些代碼最好在 視圖中處理;
- 單個(gè)模型中避免太多的場(chǎng)景.
在開(kāi)發(fā)大型復(fù)雜系統(tǒng)時(shí)應(yīng)經(jīng)常考慮最后一條建議, 在這些系統(tǒng)中,模型會(huì)很大并在很多地方使用,因此會(huì)包含需要規(guī)則集和業(yè)務(wù)邏輯, 最后維護(hù)這些模型代碼成為一個(gè)噩夢(mèng),因?yàn)橐粋€(gè)簡(jiǎn)單修改會(huì)影響好多地方, 為確保模型好維護(hù),最好使用以下策略:
定義可被多個(gè) 應(yīng)用主體 或 模塊 共享的模型基類集合。 這些模型類應(yīng)包含通用的最小規(guī)則集合和邏輯。
在每個(gè)使用模型的 應(yīng)用主體 或 模塊中, 通過(guò)繼承對(duì)應(yīng)的模型基類來(lái)定義具體的模型類,具體模型類包含應(yīng)用主體或模塊指定的規(guī)則和邏輯。
例如,在高級(jí)應(yīng)用模板,你可以定義一個(gè)模型基類common\models\Post, 然后在前臺(tái)應(yīng)用中,定義并使用一個(gè)繼承common\models\Post的具體模型類frontend\models\Post, 在后臺(tái)應(yīng)用中可以類似地定義backend\models\Post。 通過(guò)這種策略,你清楚frontend\models\Post只對(duì)應(yīng)前臺(tái)應(yīng)用,如果你修改它,就無(wú)需擔(dān)憂修改會(huì)影響后臺(tái)應(yīng)用。
您可能感興趣的文章:
- 詳解PHP的Yii框架中自帶的前端資源包的使用
- 簡(jiǎn)介PHP的Yii框架中緩存的一些高級(jí)用法
- 深入解析PHP的Yii框架中的緩存功能
- PHP的Yii框架中View視圖的使用進(jìn)階
- PHP的Yii框架中創(chuàng)建視圖和渲染視圖的方法詳解
- 詳解PHP的Yii框架中的Controller控制器
- PHP的Yii框架中移除組件所綁定的行為的方法
- PHP的Yii框架中行為的定義與綁定方法講解
- 深入講解PHP的Yii框架中的屬性(Property)
- 詳解PHP的Yii框架中擴(kuò)展的安裝與使用

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

TostaycurrentwithPHPdevelopmentsandbestpractices,followkeynewssourceslikePHP.netandPHPWeekly,engagewithcommunitiesonforumsandconferences,keeptoolingupdatedandgraduallyadoptnewfeatures,andreadorcontributetoopensourceprojects.First,followreliablesource

PHPbecamepopularforwebdevelopmentduetoitseaseoflearning,seamlessintegrationwithHTML,widespreadhostingsupport,andalargeecosystemincludingframeworkslikeLaravelandCMSplatformslikeWordPress.Itexcelsinhandlingformsubmissions,managingusersessions,interacti

TosettherighttimezoneinPHP,usedate_default_timezone_set()functionatthestartofyourscriptwithavalididentifiersuchas'America/New_York'.1.Usedate_default_timezone_set()beforeanydate/timefunctions.2.Alternatively,configurethephp.inifilebysettingdate.timez

TovalidateuserinputinPHP,usebuilt-invalidationfunctionslikefilter_var()andfilter_input(),applyregularexpressionsforcustomformatssuchasusernamesorphonenumbers,checkdatatypesfornumericvalueslikeageorprice,setlengthlimitsandtrimwhitespacetopreventlayout

ThePhpfunctionSerialize () andunserialize () AreusedtoconvertcomplexdaTastructdestoresintostoraSandaBackagain.1.Serialize () c OnvertsdatalikecarraysorobjectsraystringcontainingTypeandstructureinformation.2.unserialize () Reconstruct theoriginalatataprom

You can embed PHP code into HTML files, but make sure that the file has an extension of .php so that the server can parse it correctly. Use standard tags to wrap PHP code, insert dynamic content anywhere in HTML. In addition, you can switch PHP and HTML multiple times in the same file to realize dynamic functions such as conditional rendering. Be sure to pay attention to the server configuration and syntax correctness to avoid problems caused by short labels, quotation mark errors or omitted end labels.

The key to writing clean and easy-to-maintain PHP code lies in clear naming, following standards, reasonable structure, making good use of comments and testability. 1. Use clear variables, functions and class names, such as $userData and calculateTotalPrice(); 2. Follow the PSR-12 standard unified code style; 3. Split the code structure according to responsibilities, and organize it using MVC or Laravel-style catalogs; 4. Avoid noodles-style code and split the logic into small functions with a single responsibility; 5. Add comments at key points and write interface documents to clarify parameters, return values ??and exceptions; 6. Improve testability, adopt dependency injection, reduce global state and static methods. These practices improve code quality, collaboration efficiency and post-maintenance ease.

Yes,youcanrunSQLqueriesusingPHP,andtheprocessinvolveschoosingadatabaseextension,connectingtothedatabase,executingqueriessafely,andclosingconnectionswhendone.Todothis,firstchoosebetweenMySQLiorPDO,withPDObeingmoreflexibleduetosupportingmultipledatabas
