在使用ThinkPHP5的過程中,我經常使用db進行數據庫操作的,后來接觸到了模型(model),剛使用時感覺跟db沒啥區別,后來查官網知道模型基類中還提供了較多的其他的方法可以方便使用例如獲取器、修改器、數據完成等等功能。因此模型的功能更為強大,tp5官網推薦使用model。
就數據格式而言,在DB中是采用的數組格式使用。而在模型中統一使用對象。其中數據庫交互后涉及到格式轉換。因此在同等情況下db的數據略快與模型方式。因此對於ThinkPHP5使用DB與model的方式具體在編程中選擇哪一個按照個人的觀點並無強制要求。有時候為了項目中的封裝采用模型方式可能更為合適一些
1、模型定義
在model定義一個Blog模型類:
<?php namespace app\demo\model; use think\Model; class Blog extends Model { //默認主鍵為自動識別,如果需要指定,可以設置屬性: //protected $pk = 'uid'; }
模型會自動對應數據表,模型類的命名規則是除去表前綴的數據表名稱,采用駝峰法命名,並且首字母大寫,例如:
模型名 | 約定對應數據表(假設數據庫的前綴定義是 think_) |
---|---|
User | think_user |
UserType | think_user_type |
假設我這個類名和表名不相干的,但我這個類想操作這個表,tp5還有另一種方法:
<?php namespace app\demo\model; use think\Model; class Test extends Model { //設置數據表(不含前綴) protected $name = 'blog'; //設置完整的數據表 // protected $table = 'tp_codes'; }
2、模型調用
模型類可以使用靜態調用或者實例化調用兩種方式,例如:
//靜態調用 $blog = Blog::get(1);//以id為1作為條件(自動根據主鍵來查) // 實例化模型 $blog = new Blog(); // 使用 Loader 類實例化(單例) $blog = Loader::model('Blog'); // 或者使用助手函數`model` $blog = model('Blog');
3、使用模型增刪查改
(1)模型查詢操作
//查詢 $blog = Blog::get(2);//以id為1作為條件(自動根據主鍵來查) echo $blog->title;//輸出:php實戰 $user = new User(); // 查詢單個數據 $user->where('name', 'thinkphp') ->find(); //多條件查詢,可以傳入數組作為查詢條件 $bolg = Blog::get(['title'=>'模型1','content'=>'模型內容2']); $bolg = Blog::where(['title'=>'模型1','content'=>'模型內容2'])->find(); echo $bolg->id; //查詢全部 $bolg = Blog::all(); foreach($bolg as $key=>$v){ echo $v->title."<br>"; } $user = new User(); // 查詢數據集 $user->where('name', 'thinkphp') ->limit(10) ->order('id', 'desc') ->select();
動態查詢:通過getByxxx()進行條件查詢,后面的xxx是字段名稱(按駝峰命名)
//根據某個條件查詢數據 getByxxx() 方法 $bolg = Blog::getByTitle('模型1'); echo $bolg->content;
(2)模型添加操作
$blog = new Blog() //添加單條 $blog->title = '模型'; $blog->author = 'lhs'; $blog->publish_time = '11'; $blog->content = '模型內容'; $blog->save(); //批量新增 $list = [ ['title'=>'模型1','author'=>'lhs','publish_time'=>'12','content'=>'模型內容2'], ['title'=>'模型2','author'=>'lhs','publish_time'=>'13','content'=>'模型內容3'] ]; if($blog->saveAll($list)){ echo '用戶添加成功!'; }
或者使用isUpdate進行添加操作
//用這個方法添加數據 $blog = Blog::get(1); $blog->title = 'get添加模型'; $blog->author = 'lhs'; $blog->publish_time = '1568908800'; $blog->content = '模型內容'; $blog->id = null; if($blog->isUpdate(false)->save()){ echo "添加成功!"; }
注:要把id設置為空,不然報主鍵重復的錯誤
(3)模型更新操作
//更新 $blog = new Blog(); $blog->id = 24; $blog->title = '更新模型'; $blog->author = 'lhs'; $blog->publish_time = '1572919302'; $blog->content = '模型內容'; $blog->isUpdate()->save(); //調用這個方法,isUpdate改true(即默認是更新操作) $blog = Blog::get(1); $blog->title = '更新模型'; $blog->author = 'lhs'; $blog->publish_time = '1553011200'; $blog->content = '模型內容'; if($blog->save()){ echo "更新成功!"; }
(4)模型刪除操作
$bolg = Blog::get(25); $bolg->delete(); Blog::destroy(26);
4、讀取器和修改器
讀取器的作用是在獲取數據的字段值后自動進行處理,修改器的作用是可以在數據賦值的時候自動進行轉換處理,例如:
<?php namespace app\demo\model; use think\Model; class Codes extends Model { //讀取器 public function getPublishTimeAttr($value) { return date("Y-m-d H:i",$value); } //$data為獲取整個對象 public function getNameAttr($value,$data) { return '書名:'.$data['name'].',價格:'.$data['price']; } //修改器 public function setPublishTimeAttr($value) { return strtotime($value); } }
使用讀取器和修改器
public function read(){ //讀取器的方法命名規范:get+屬性名(駝峰命名法)+Attr /*$code = Codes::get(1); echo $code->publish_time; //如果自定義了getXXXAttr就調用,沒有自定義就原樣輸出 echo $code->name;*/ //添加 $code = new Codes(); $code->name = '支付寶基金'; $code->category = '經濟'; $code->price = '161'; $code->publish_time = '2019-9-27';//調用setPublishTimeAttr方法,在添加是自動轉為時間戳 $code->save(); }
5、類型轉換
integer:設置為integer(整型)后,該字段寫入和輸出的時候都會自動轉換為整型。
float:該字段的值寫入和輸出的時候自動轉換為浮點型。
boolean:該字段的值寫入和輸出的時候自動轉換為布爾型。
array:如果設置為強制轉換為
array
類型,系統會自動把數組編碼為json格式字符串寫入數據庫,取出來的時候會自動解碼。
object:該字段的值在寫入的時候會自動編碼為json字符串,輸出的時候會自動轉換為
stdclass
對象。
serialize:指定為序列化類型的話,數據會自動序列化寫入,並且在讀取的時候自動反序列化。
json:
指定為json
類型的話,數據會自動json_encode
寫入,並且在讀取的時候自動json_decode
處理。
timestamp:指定為時間戳字段類型的話,該字段的值在寫入時候會自動使用
strtotime
生成對應的時間戳,輸出的時候會自動轉換為dateFormat
屬性定義的時間字符串格式,默認的格式為Y-m-d H:i:s
例子:
//類型轉換 protected $type = [ 'publish_time' => 'timestamp:Y-m-d', 'name' => 'serialize'//序列化 ];
在修改數據時自動轉換類型
//自動轉換,修改 $code = new Codes(); $code->name = ['中國的經濟','金融危機','美國的經濟霸權']; $code->category = '經濟'; $code->price = '132161'; $code->publish_time = '2019-12-27';//調用setPublishTimeAttr方法,在添加是自動轉為時間戳 $code->save();
6、自動完成
數據自動完成指在不需要手動賦值的情況下對字段的值進行處理后寫入數據庫。
系統支持auto
、insert
和update
三個屬性,可以分別在寫入、新增和更新的時候進行字段的自動完成機制,auto屬性自動完成包含新增和更新操作,例如:
//自動完成,更新 protected $update = [ 'category' => '經濟' ]; //自動完成,新增 protected $insert = [ 'category' => '經濟' ];
自動完成對category更新和添加
//自動完成,更新 $code = Codes::get(4); $code->name = '支付寶的霸權'; $code->save(); //自動完成,新增 $code = new Codes(); $code->name = '中國經濟霸權'; $code->price = '270000'; $code->publish_time = '2019-12-27'; $code->save();
以上的自動完成都是對category固定賦值,如果想動態自動完成就結合修改器
//自動完成 protected $update = [ // 'category' => '經濟' 'category' ]; public function setNameAttr($value,$data) { return $data['category'] == '經濟' ? '國家經濟' : '其他'; }
//自動完成配合修改器,更新 $code = Codes::get(4); $code->name = '美國'; $code->publish_time = '2019-12-2'; $code->save();
結果如下:
7、查詢范圍
可以對模型的查詢和寫入操作進行封裝,例如:
//查詢范圍 protected function scopeName($query,$a){ $query->where("name",$a); } protected function scopeCategory($query,$a){ $query->where('category',$a); } //全局查詢范圍,就算不調用也會自動加上 protected static function base($query){ $query->where('id',2); }
就可以進行下面的條件查詢:
//查詢范圍 $code = Codes::scope('name','php實戰') ->scope('category','PHP') ->scope(function($query){ $query->order('id','desc'); }) ->all();
運行結果: