Yii中Model(模型)的創(chuàng)建及使用方法
本文實(shí)例分析了Yii中Model(模型)的創(chuàng)建及使用方法。分享給大家供大家參考,具體如下:
YII 實(shí)現(xiàn)了兩種模型,表單模型(CFormModel類)和Active Record模型(CAtiveRecord類),它們都繼承自CModel類。 CFormModel代表的數(shù)據(jù)模型是從HTML表單收集的輸入,封裝了所有邏輯(如表單的驗(yàn)證和其它業(yè)務(wù)邏輯,應(yīng)用到表單的域上)。它能將數(shù)據(jù)存儲(chǔ)在內(nèi) 存中,或者在一個(gè)Active Record的幫助下,存入數(shù)據(jù)庫里。
數(shù)據(jù)庫連接操作
在config/main.php中
'db'=>array( 'connectionString' => 'mysql:host=localhost;dbname=oss', 'emulatePrepare' => true, 'username' => 'root', 'password' => 'hahaha', 'charset' => 'utf8', //表前綴 'tablePrefix'=>"oss_" ),
打開注釋,php要支持pdo
查看操作日志
//顯示日志信息,包括sql的查詢信息 array( 'class'=>'CWebLogRoute', ),
將注釋打開
一. 基于CActiveRecord的Model
Active Record(AR) 是一種設(shè)計(jì)模式,用面向?qū)ο蟮姆绞匠橄蟮脑L問數(shù)據(jù),Yii中,每一個(gè)AR對(duì)象的實(shí)例都可以是CActiveRecord類或者它的子類。它包裝了數(shù)據(jù)庫表 或視圖中的一行記錄,并封裝了所有的邏輯和風(fēng)聞數(shù)據(jù)庫的細(xì)節(jié),有大部分的業(yè)務(wù)邏輯,必須使用這種模型。數(shù)據(jù)庫表中一行每列字段的值對(duì)應(yīng)AR對(duì)象的一個(gè)屬 性。它將表映射到類,行映射到對(duì)象,列則映射到對(duì)象的數(shù)據(jù)。也就是說每一個(gè)Active Record類的實(shí)例代表了數(shù)據(jù)庫中表的一行。但一個(gè) Active Record類不單單是數(shù)據(jù)庫表中的字段跟類中屬性的映射關(guān)系。它還需要在這些數(shù)據(jù)上處理一些業(yè)務(wù)邏輯,定義了所有對(duì)數(shù)據(jù)庫的讀寫操作。
1) 聲明一個(gè)基于CActiveRecord 類的Model
class Post extends CActiveRecord { public static function model($className=__CLASS__) { return parent::model($className); } public function tableName() { return '{{post}}'; } public function primaryKey() { return 'id'; // return array('pk1', 'pk2'); } }
2) 使用父類的方法完成數(shù)據(jù)庫操作
(1) Insert:
$post=new Post; $post->title='sample post'; $post->content='content for the sample post'; $post->create_time=time(); $post->save();
(2) Select: 常用幾種方法
// find the first row satisfying the specified condition $post=Post::model()->find($condition,$params); // find the row with the specified primary key $post=Post::model()->findByPk($postID,$condition,$params); // find the row with the specified attribute values $post=Post::model()->findByAttributes($attributes,$condition,$params); // find the first row using the specified SQL statement $post=Post::model()->findBySql($sql,$params); $criteria=new CDbCriteria; $criteria->select='title'; // only select the 'title' column $criteria->condition='postID=:postID'; $criteria->params=array(':postID'=>10); $post=Post::model()->find($criteria); $post=Post::model()->find(array( 'select'=>'title', 'condition'=>'postID=:postID', 'params'=>array(':postID'=>10), )); // find all rows satisfying the specified condition $posts=Post::model()->findAll($condition,$params); // find all rows with the specified primary keys $posts=Post::model()->findAllByPk($postIDs,$condition,$params); // find all rows with the specified attribute values $posts=Post::model()->findAllByAttributes($attributes,$condition,$params); // find all rows using the specified SQL statement $posts=Post::model()->findAllBySql($sql,$params); // get the number of rows satisfying the specified condition $n=Post::model()->count($condition,$params); // get the number of rows using the specified SQL statement $n=Post::model()->countBySql($sql,$params); // check if there is at least a row satisfying the specified condition $exists=Post::model()->exists($condition,$params);
(3) Update
// update the rows matching the specified condition Post::model()->updateAll($attributes,$condition,$params); // update the rows matching the specified condition and primary key(s) Post::model()->updateByPk($pk,$attributes,$condition,$params); // update counter columns in the rows satisfying the specified conditions Post::model()->updateCounters($counters,$condition,$params);
(4) Delete
$post=Post::model()->findByPk(10); // assuming there is a post whose ID is 10 $post->delete(); // delete the rows matching the specified condition Post::model()->deleteAll($condition,$params); // delete the rows matching the specified condition and primary key(s) Post::model()->deleteByPk($pk,$condition,$params);
(5) 使用事務(wù)
$model=Post::model(); $transaction=$model->dbConnection->beginTransaction(); try { // find and save are two steps which may be intervened by another request // we therefore use a transaction to ensure consistency and integrity $post=$model->findByPk(10); $post->title='new post title'; $post->save(); $transaction->commit(); } catch(Exception $e) { $transaction->rollBack(); }
二. 基于CFormModel 的Model
編寫表單需要的HTML之前,我們需要決定我們希望用戶輸入哪些數(shù)據(jù),以及應(yīng)該符合什么規(guī)則。一個(gè)模型類可以用來記錄這些信息,模型是保持用戶輸入并進(jìn)行驗(yàn)證的核心
根據(jù)我們?nèi)绾问褂糜脩舻妮斎?,我們可以?chuàng)建兩種類型的模型。如果用戶輸入的數(shù)據(jù)被收集,使用,然后丟棄,我們將創(chuàng)建一個(gè)表單模型(form model); 如果用戶輸入的數(shù)據(jù)被保存到數(shù)據(jù)庫中,我們則會(huì)使用 active record 。這兩種模型都繼承了他們相同的基類CModel中定義的表單的通用接 口。
1) 模型類的定義
下面的例子中,我們創(chuàng)建了一個(gè)LoginForm模型,用來收集用戶在登陸頁面的輸入。由于登陸信息僅僅用于用戶驗(yàn)證,并不需要保存,因此我們用form model創(chuàng)建
class LoginForm extends CFormModel { public $username; public $password; public $rememberMe=false; }
LoginForm一共聲明了三個(gè)屬性(attributes),$username、$password、$rememberMe
用來記錄用戶輸入的用戶名、密碼、以及是否記住登陸的選項(xiàng)。因?yàn)?rememberMe有了默認(rèn)值false,所以顯示表單時(shí)對(duì)應(yīng)的選框是沒有勾選的。
提示:我們使用名"attributes",而不是"properties",來把他們和正常的屬性(properties)進(jìn)行區(qū)分。
2) 聲明驗(yàn)證規(guī)則
一旦把用戶提交的數(shù)據(jù)填充到模型,在使用之前,我們要檢查他們是否合法。這是通過對(duì)輸入進(jìn)行一組規(guī)則驗(yàn)證實(shí)現(xiàn)的。我們?cè)趓ulers()方法中通過配置一個(gè)數(shù)組來定義驗(yàn)證規(guī)則
class LoginForm extends CFormModel { public $username; public $password; public $rememberMe=false; private $_identity; public function rules() { return array( array('username, password','required'), array('rememberMe', 'boolean'), array('password', 'authenticate'), ); } public function authenticate($attribute,$params) { if(!$this->hasErrors()) // we only want to authenticate when no input errors { $this->_identity=new UserIdentity($this->username,$this->password); if(!$this->_identity->authenticate()) $this->addError('password','Incorrect password.'); } } }
上面的代碼指明了用戶名和密碼是必須得,密碼需要被驗(yàn)證,rememberMe必須是布爾型
rules()中返回的每條規(guī)則,必須按照如下格式
array('AttributeList', 'Validator', 'on'=>'ScenarioList', ...附加選項(xiàng)(additional options))
AttributeList 是一個(gè)被逗號(hào)分隔的需要驗(yàn)證的屬性名列表。Validator 指出了需要做怎樣的驗(yàn)證??蛇x的on 參數(shù)指出了該規(guī)則應(yīng)用的場景列表,(additional options)是對(duì)應(yīng)的name-value,用于初始對(duì)應(yīng)驗(yàn)證器的相關(guān)屬性
在一個(gè)規(guī)則中指定Validator有三種方法,首先Validator可以使該類的一個(gè)方法,比如上面例子中的authenticate。該Validator方法必須按照如下的格式聲明
其次 Validator 可以使驗(yàn)證器的類名,當(dāng)規(guī)則適用時(shí),一個(gè)驗(yàn)證器類的實(shí)例會(huì)被創(chuàng)建并進(jìn)行實(shí)際的驗(yàn)證。規(guī)則里的附加屬性,用于初始實(shí)例的相關(guān)屬性。驗(yàn)證器類必須繼承于CValidator
提示:當(dāng)對(duì)active record模型指定規(guī)則的時(shí)候,我們可以使用特殊的參數(shù)‘on',
該參數(shù)可以使'insert' 或者 'update',可以讓規(guī)則分別在插入或者更新的時(shí)候適用。如果沒有生命,該規(guī)則會(huì)在任何調(diào)用save()的時(shí)候適用。
第三、Validator 可以使驗(yàn)證器類預(yù)先定義的別名。在上面的例子中,“required”便是CRequiredValidator的別名,用來驗(yàn)證屬性不能為空。下面是預(yù)定義的驗(yàn)證器類別名的列表
? boolean:CBooleanValidator的別名,驗(yàn)證屬性的值是否是CBooleanValidator::trueValue 或者 CBooleanValidator::falseValue
? captcha:CCaptchaValidator的別名,驗(yàn)證屬性的值是否和CAPTCHA中顯示的驗(yàn)證碼的值相等
? compare:CCompareValidator的別名,驗(yàn)證屬性的值是否等于另一個(gè)屬性或者一個(gè)常量
? email:CEmailValidator的別名,驗(yàn)證屬性的值是否是個(gè)合法的email地址
? default:CDefaultValueValidator的別名,為屬性指派一個(gè)默認(rèn)值
? exist:CExistValidator的別名,驗(yàn)證屬性的值是否能在表的列里面找到
? file: CFileValidator 的別名, 驗(yàn)證屬性是否包含上傳文件的名字
? filter:CFilterValidator的別名,使用一個(gè)過濾器轉(zhuǎn)換屬性的形式
? in: CRangeValidator 的別名, 驗(yàn)證屬性值是否在一個(gè)預(yù)訂的值列表里面
? length: CStringValidator 的別名, 確保了屬性值的長度在指定的范圍內(nèi).
? match: CRegularExpressionValidator 的別名, 驗(yàn)證屬性是否匹配一個(gè)正則表達(dá)式.
? numerical: CNumberValidator 的別名, 驗(yàn)證屬性是否是一個(gè)有效的數(shù)字.
? required: CRequiredValidator 的別名, 驗(yàn)證屬性的值是否為空.
? type: CTypeValidator 的別名, 驗(yàn)證屬性是否是指定的數(shù)據(jù)類型.
? unique: CUniqueValidator 的別名, 驗(yàn)證屬性在數(shù)據(jù)表字段中是否是唯一的.
? url: CUrlValidator 的別名, 驗(yàn)證屬性是否是一個(gè)有效的URL路徑.
下面我們給出一些使用預(yù)定義驗(yàn)證器的例子。
// username is required array('username', 'required'), // username must be between 3 and 12 characters array('username', 'length', 'min'=>3, 'max'=>12), // when in register scenario, password must match password2 array('password', 'compare', 'compareAttribute'=>'password2', 'on'=>'register'), // when in login scenario, password must be authenticated array('password', 'authenticate', 'on'=>'login'),
3) 安全屬性的設(shè)置
當(dāng)一個(gè)模型創(chuàng)建之后,我們往往需要根據(jù)用戶的輸入,為它填充屬性。這可以方便的通過下面批量賦值的方式來實(shí)現(xiàn)
$model=new LoginForm; if(isset($_POST['LoginForm'])) $model->attributes=$_POST['LoginForm'];
最后那條語句便是批量賦值,把$_POST['LoginForm']中每個(gè)屬性都賦值到對(duì)應(yīng)的模型屬性中,它等價(jià)于下面的語句
foreach($_POST['LoginForm'] as $name=>$value) { if($name is a safe attribute) $model->$name=$value; }
聲明屬性是否是安全屬性是個(gè)至關(guān)重要的工作。例如,如果我把把數(shù)據(jù)表的主鍵暴露為安全屬性,那么便可以通過修改主鍵的值,來管理本沒有權(quán)限管理的數(shù)據(jù),進(jìn)行攻擊。
4) 1.1版中的安全屬性
在1.1版中,如果屬性在適用的規(guī)則中指定了驗(yàn)證器,則認(rèn)為是安全的。例如
array('username, password', 'required', 'on'=>'login, register'), array('email', 'required', 'on'=>'register'),
上面的代碼中用戶名和密碼屬性在login的場景下不允許為空。用戶名、密碼郵箱在register的場景下不允許為空。因此如果在login的場景下 進(jìn) 行批量賦值,僅僅用戶名和密碼會(huì)被賦值,因?yàn)閘ogin場景下驗(yàn)證規(guī)則里僅出現(xiàn)了這兩個(gè)屬性,但是如果是在register場景下,那么這三個(gè)屬性都 會(huì)被 賦值。
// in login scenario $model=new User('login'); if(isset($_POST['User'])) $model->attributes=$_POST['User']; // in register scenario $model=new User('register'); if(isset($_POST['User'])) $model->attributes=$_POST['User'];
那么為什么我們使用如此的策略來決定一個(gè)屬性是否是安全屬性呢?因?yàn)橐粋€(gè)屬性,已經(jīng)有了一個(gè)或者多個(gè)對(duì)個(gè)進(jìn)行校驗(yàn)的規(guī)則,那么我還需要擔(dān)心嗎?
需要記住的是,驗(yàn)證器是用來檢測用戶輸入的數(shù)據(jù),而不是我們用代碼產(chǎn)生的數(shù)據(jù)(例如 時(shí)間戳,自增的主鍵等)。因此不要給那些不需要用戶輸入的屬性添加驗(yàn)證器。
有時(shí)候我們想聲明一些屬性為安全屬性,但是又不必給指定一個(gè)驗(yàn)證規(guī)則。例如文章的正文屬性,我們可以允許用戶的任何輸入。為了實(shí)現(xiàn)這個(gè)目標(biāo),我們可以用safe規(guī)則。
對(duì)應(yīng)的也有一個(gè)unsafe規(guī)則,來指定哪些屬性是不安全的
unsafe并不常用,對(duì)你以前定義的安全屬性來說,這是個(gè)例外
5) 獲取驗(yàn)證錯(cuò)誤
當(dāng)驗(yàn)證結(jié)束后,任何可能的錯(cuò)誤都存儲(chǔ)在模型的實(shí)例中。我們可以通過調(diào)用CModel::getErrors() 和 CModel::getError()重新獲取到。這兩個(gè)方法的區(qū)別在于,第一個(gè)可以返回指定模型屬性的所有錯(cuò)誤,而第二個(gè)方法只返回了第一條錯(cuò)誤。
6) 屬性標(biāo)簽
設(shè)計(jì)表單的時(shí)候,我們需要為用戶的輸入框顯示一個(gè)標(biāo)簽,來提示用戶輸入。盡管我們可以再form中寫死,但是如果我們?cè)谙鄳?yīng)的模型中指定的話會(huì)更加方便和靈活
默認(rèn)情況下,CModel 會(huì)簡單的返回屬性的名字作為標(biāo)簽。這可以通過重寫attributeLabels() 方法來自定義。在接下來章節(jié)中我們將看到,在模型中指定標(biāo)簽可以讓我們更快更強(qiáng)大的創(chuàng)建一個(gè)form表單
希望本文所述對(duì)大家基于yii框架的php程序設(shè)計(jì)有所幫助。
- YII2框架中自定義用戶認(rèn)證模型,完成登陸和注冊(cè)操作示例
- Yii2.0框架模型添加/修改/刪除數(shù)據(jù)操作示例
- Yii2.0框架模型多表關(guān)聯(lián)查詢示例
- yii框架表單模型使用及以數(shù)組形式提交表單數(shù)據(jù)示例
- PHP YII框架開發(fā)小技巧之模型(models)中rules自定義驗(yàn)證規(guī)則
- PHP的Yii框架中Model模型的學(xué)習(xí)教程
- Yii框架數(shù)據(jù)模型的驗(yàn)證規(guī)則rules()被執(zhí)行的方法
- YII動(dòng)態(tài)模型(動(dòng)態(tài)表名)支持分析
- Yii框架表單模型和驗(yàn)證用法
- Yii模型操作之criteria查找數(shù)據(jù)庫的方法
- Yii數(shù)據(jù)模型中rules類驗(yàn)證器用法分析
- yii2.0框架多模型操作示例【添加/修改/刪除】
相關(guān)文章
yii框架builder、update、delete使用方法
這篇文章主要介紹了yii框架builder、update、delete使用方法,需要的朋友可以參考下2014-04-04PHP基于ip2long實(shí)現(xiàn)IP轉(zhuǎn)換整形
這篇文章主要介紹了PHP基于ip2long實(shí)現(xiàn)IP轉(zhuǎn)換整形,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12PHP實(shí)現(xiàn)微信公眾號(hào)驗(yàn)證Token的示例代碼
這篇文章主要介紹了PHP實(shí)現(xiàn)微信公眾號(hào)驗(yàn)證Token的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12CodeIgniter實(shí)現(xiàn)更改view文件夾路徑的方法
這篇文章主要介紹了CodeIgniter實(shí)現(xiàn)更改view文件夾路徑的方法,需要的朋友可以參考下2014-07-07PHP array_reduce()函數(shù)的應(yīng)用解析
這篇文章主要介紹了PHP array_reduce()的應(yīng)用,本文通過代碼舉例給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-10-10關(guān)于php微信訂閱號(hào)開發(fā)之token驗(yàn)證后自動(dòng)發(fā)送消息給訂閱號(hào)但是沒有消息返回的問題
最近做了個(gè)項(xiàng)目,當(dāng)token驗(yàn)證之后,發(fā)送消息給訂閱號(hào),但是沒有消息返回,下面小編通過本篇文章給大家分享我的解決辦法2015-12-12