簡介
tp5的model只做業(yè)務(wù)層操作,不做具體的鏈接數(shù)據(jù)庫sql操作痹届。
think\db\Connection.php做鏈接數(shù)據(jù)庫操作
think\db\Builder.php做創(chuàng)建sql操作
think\db\Query.php做數(shù)據(jù)CURD操作
功能清單
數(shù)據(jù)自動完成
自動寫入時間戳
時間字段自動格式化輸出字段
字段驗證器
自動關(guān)聯(lián)寫入
只讀字段
隱藏字段
事件回調(diào)
軟刪除
類型轉(zhuǎn)換
功能詳情
- 數(shù)據(jù)自動完成
//設(shè)置自動完成的字段,支持鍵值對數(shù)組和索引數(shù)組
//新增和更新時都會使用
//如:['name'=>'zhangsan','sex'=>'男']
// ['name','sex']
protected $auto = [];
//新增 自動完成列表
//只在新增數(shù)據(jù)的時候使用
protected $insert = [];
//更新 自動完成列表
//只在更新數(shù)據(jù)的時候使用
protected $update = [];
//用來標(biāo)記當(dāng)前操作被修改的字段
//如 ['name','sex']
protected $change = [];
//依賴方法,model類會自動調(diào)用解析auto數(shù)組
//我們只需配置auto數(shù)組即可
protected function autoCompleteData($auto = []){}
在model中設(shè)置完auto字段后在更新或新增的時候首先會判斷auto中設(shè)置的字段是否存在于被更新的字段($this->change)中
如果存在則不用auto里設(shè)置的字段和值
如果不存在則將auto里設(shè)置的字段和值添加到this?>data中并把該字段新增到this->change中他巨。
如果auto是索引數(shù)組窥突,也就是只設(shè)置了字段名,沒有設(shè)置子字段值劲装,這是就會根據(jù)字段名去$this->data中查詢該字段值,并添加的到要更新的屬性數(shù)組中去昌简。
新增數(shù)據(jù)的方法是create, 修改數(shù)據(jù)的方法是update,批量新增和修改的方法是saveAll,這幾個方法的最終實現(xiàn)都是調(diào)用的save方法
saveAll方法批量新增和修改占业,并不是組合sql語句,而是開啟事務(wù)纯赎,然后調(diào)用save方法谦疾,一條一條添加和修改,最后提交事務(wù)犬金。
在更新操作中念恍,model會自動檢查data的所有字段的值是否被更改,只會跟新被更改過得字段的值晚顷。沒被更改的則被忽略峰伙。
insert、update的功能和auto的功能類似该默,只不過auto是不管是新增數(shù)據(jù)和是更新數(shù)據(jù)都會使用瞳氓,而insert值針對新增,update只針對更新栓袖。如果設(shè)置了相同的屬性匣摘,insert和update的則會覆蓋auto中的字段。
- 自動寫入時間戳
//是否需要自動寫入時間戳
//可以是字符串類型和boolean類型
//字符串類型代表要寫入的時間格式
//如: 'Y-m-d H:i:s'
//boolean類型就是true和false裹刮,代表是否開啟
//默認(rèn)時間格式為int類型
protected $autoWriteTimestamp;
//默認(rèn)自動寫入的字段有
//創(chuàng)建時間和更新時間音榜,他們對應(yīng)的字段名分別是
//create_time,和update_time
//也可以在model里自己設(shè)置。
protected $createTime = 'create_time';
protected $updateTime = 'update_time';
配置方式
該配置TP5默認(rèn)為false,需要手動開啟
在數(shù)據(jù)庫配置(database.php)中添加全局配置捧弃。
'auto_timestamp' => true
//或者設(shè)置時間格式
// 'auto_timestamp' => 'datatime'
在單獨的模型類里設(shè)置
protected $autoWriteTimestamp = true;
//或者設(shè)置時間格式
// protected $autoWriteTimestamp = 'datatime';
知識的字段類型 timestamp/datetime/int
如果自己的數(shù)據(jù)字段不是默認(rèn)值得話赠叼,可以在自己的model里修改。
//如:
protected $createTime = 'my_create_time_filed';
protected $updateTime = 'my_careate_time_field';
如果只需要createTime而不需要updateTIme塔橡,則可以在model中關(guān)閉updateTIme
//如
protected $updateTime = false;
在model中開啟和關(guān)閉只針對單獨的model起作用梅割,想要全局起作用還是要在配置文件里配置霜第。
- 時間字段自動格式化輸出
//輸出格式
protected $dateFormat;
配置方式
該配置TP5模式輸出格式為 ‘Y-m-d H:i:s’
可以自己在數(shù)據(jù)庫配置文件(database.php)中配置葛家。如
'datetime_format' => 'Y/m/d H:i',
也可以在model中設(shè)置
protected $dateFormat = 'Y/m/d H:i';
- 字段驗證器
//字段驗證規(guī)則
protected $validate = [];
//是否采用批量驗證
protected $batchValidate = false;
/**
* 設(shè)置字段驗證
* @access public
* @param array|string|bool $rule 驗證規(guī)則 true表示自動讀取驗證器類
* @param array $msg 提示信息
* @param bool $batch 批量驗證
* @return $this
*/
public function validate($rule = ture,$msg=[],$bath=false){}
/**
* 自動驗證數(shù)據(jù)
* @access protected
* @param array $data 驗證數(shù)據(jù)
* @param mixed $rule 驗證規(guī)則
* @param bool $batch 批量驗證
* @return bool
*/
public function validateData($data,$rule=null,$batch=null){}
使用方式
在model中配置字段驗證規(guī)則,在整個model中新增和更新操作都通用。
// 優(yōu)點:只需要設(shè)置一次泌类,即可通用
// 缺點:無法針對化設(shè)置
//比如:新增用戶和編輯用戶功能癞谒,
//新增是密碼為必填項底燎,編輯時密碼就是選填項了
//所以就不能再model里設(shè)置密碼的驗證規(guī)則了,
這個時候就只能在新增的action里為密碼做驗證了弹砚。
protected $validate = [
'rule' => [
'name' => 'require',
//多個規(guī)則可以是用字符串用|分隔
//也可以使用數(shù)組['require','number','min'=>10,'max'=>80]
//使用字符串配置要被使用explode('|',$rule)轉(zhuǎn)化成數(shù)組双仍,所以使用數(shù)組配置效率更高
'age' => 'require|number|min:10|max:80',
'height' => 'between:100,200'
],
'msg' => [
'name' => 'name不能為空',
'age.require' => 'age不能沒空',
'age.number' => 'age必須是一個數(shù)字',
'age.min' => 'age最小為10',
'age.max' => 'age最大為80',
'height' => 'height只能在100到200之間'
]
];
在具體操作時調(diào)用think\Validate類來實現(xiàn)
//在類的頭部,因為Validate文件桌吃。
use think\Validate;
$validate = new Validate([
'name' => 'require',
'age' => 'require|number|min:10|max:80'
],[
'name' => 'name不能為空',
'age.require' => 'age不能沒空',
'age.number' => 'age必須是一個數(shù)字',
'age.min' => 'age最小為10',
'age.max' => 'age最大為80',
]);
//使用check檢查數(shù)據(jù)
if($validate->check($data)){
echo '數(shù)據(jù)格式符合要求';
}else{
//比如:name不能為空
echo $validate->getError();
}
對比
使用第一種方法在model里設(shè)置驗證規(guī)則朱沃,雖然說結(jié)構(gòu)看著比較合理,但是這種方法靈活性比較低茅诱,因為他是在save的時候去判斷的逗物,如果save失敗,你不清楚是數(shù)據(jù)驗證失敗瑟俭,還是說插入到數(shù)據(jù)失敗翎卓。所以對于做提示驗證很麻煩(因為數(shù)據(jù)驗證的提示我們是直接返回給用戶的,而數(shù)據(jù)庫操作的提示一般我們是不返回給用戶的摆寄,所以得到結(jié)果后還要做判斷失暴,先對比較麻煩)。
使用第二種方法在action里定義一個_validate的函數(shù)微饥,專門用來做數(shù)據(jù)校驗逗扒,這中方法比較靈活,而且他是在在保存數(shù)據(jù)之前做的校驗欠橘,所以返回結(jié)果分的比較清楚缴阎,對用戶的提示也比較清晰,代碼可讀性也比較好简软。
- 自動關(guān)聯(lián)寫入
// 關(guān)聯(lián)對象
protected $relation;
// 關(guān)聯(lián)自動寫入(關(guān)聯(lián)的屬性名)
protectd $relationWrite = [];
暫時沒有使用蛮拔,后續(xù)再繼續(xù)不補充。
- 只讀字段
//用來保護(hù)那些不許要被更新的字段痹升。
//比如建炫,創(chuàng)建時間
//設(shè)置后再更新數(shù)據(jù)時,會字段過濾掉create_time字段
//避免更新到數(shù)據(jù)庫疼蛾。
protected $readonly = ['create_time'];
- 隱藏字段
//設(shè)置要隱藏的字段肛跌,
//該設(shè)置只在toArray(),和subToArray()方法中起作用
protected $hidden = [];
//相關(guān)方法
public function hidden($hidden=[],$override=false){
}
當(dāng)使用toArray和subToArray獲得數(shù)組數(shù)據(jù)時,使用hidden字段和hidden函數(shù)可以隱藏數(shù)組中的元素察郁。如:
//user表的屬性字段(模擬操作)
user_field = ['name','sex','age','height'];
在User模型中設(shè)置$hidden字段
protected $hidden = ['age','height'];
dump($User->toArray()); //只有name和sex字段衍慎。
//也可以調(diào)用hidden方法隱藏字段
//會有 name,age,height 三個字段
dump($User->hidde(['sex'])->toArray());
//只有name字段了
//第二個參數(shù)標(biāo)識是否合并 $this->hidden
dump($user->hidden(['sex'],true)->toArray());
- 事件回調(diào)
支持的回調(diào)事件
before_insert 新增前
after_insert 新增后
before_update 更新前
after_update 更新后
before_write 寫入前(新增和更新都會調(diào)用)
after_write 寫入后(新增和更新都會調(diào)用)
before_delete 刪除前
after_delete 刪除后
注冊的回調(diào)方法支持傳入一個參數(shù),當(dāng)前示例模型對象皮钠,并且before_write,before_insert,before_update,before_delete返回false會結(jié)束執(zhí)行稳捆。
使用方法
控制器里使用
//支持給一個位置注冊多個事件
User::event('before_insert',function($user){
if($user->status != 1){
return false;
}
});
//這個也會生效,回到函數(shù)為beforeInsert
User::event('before_insert','beforeInsert');
模型里使用
//使用init方法統(tǒng)一注冊模型事件
class User extends Model{
protected static function init(){
User::event('before_insert',function($user){
if($user->status != 1){
return false;
}
}
//注冊第二個事件
User::event('before_insert','beforeInsert');
}
}
原理
model類里有一個protected static $event = [];屬性麦轰,注冊的時間都存放在這個屬性中乔夯。比如:
$event = [
//模型名稱
'user' => [
//事件名稱
'before_insert' => [
'callback_funciton','beforeInsert'
],
'after_insert' => [
'callback_function','afterInsert'
],
'before_delete' => [
'beforeDelete'
]
]
]
注冊事件時砖织,把所有的事件都保存在$event中了,然后在insert末荐,update,delete等相應(yīng)的位置調(diào)用即可侧纯。
- 軟刪除
簡介
在實際項目中,對數(shù)據(jù)頻繁的使用刪除操作可能會導(dǎo)致性能問題甲脏,軟刪除的作用就是給數(shù)據(jù)加上刪除標(biāo)記眶熬,而不是真正的刪除,同時也便于需要的時候恢復(fù)數(shù)據(jù)块请。
設(shè)置方式
使用軟刪除功能需要引用SoftDelete trait;如:
namespace app\index\model;
use think\Model;
use think\model\SoftDelete;
class User extends Model{
// 使用SoftDelete
// trait 的使用方式
// 使用trait跟類的繼承相似
use SoftDelete;
//軟刪除標(biāo)記的字段名
protected $deleteTime = 'delete_time';
}
dateteTIme屬性用于標(biāo)記數(shù)據(jù)表里的軟刪除字段聋涨,TP5里的軟刪除使用的是int類型,默認(rèn)值為null(這個很重要负乡,因為查詢的時候是用delete_time is not null 來查詢的),用于記錄刪除時間牍白。
可以用類型轉(zhuǎn)換指定軟刪除的字段類型,建議數(shù)據(jù)表里的所有時間字段使用同一種數(shù)據(jù)類型抖棘。
使用方式
在model中設(shè)置好后茂腥,就可以直接使用了
//軟刪除
User::destory(1);
//真刪除
User::destory(1,true);
//軟刪除
$user = User::get(1);
$user->delete();
//真刪除
$user->delete(true);
默認(rèn)情況下,查詢出來的數(shù)據(jù)是不包括軟刪除的數(shù)據(jù)的切省,如果想要查詢包括軟刪除的數(shù)據(jù)最岗,可以使用下面的方式。
User::withTrashed()->find();
User::withTrashed()->select();
1
2
3
如果僅需要查詢軟刪除的數(shù)據(jù)朝捆,可以這樣:
User::onlyTranshed()->find();
User::onlyTranshed()->select();
- 類型轉(zhuǎn)換
TP5支持給數(shù)據(jù)表中的字段設(shè)置類型般渡,并會在讀取和寫入的時候自動轉(zhuǎn)換。如:
class User extends Model{
protected $type = [
'status' => 'integer',
'score' => 'float',
'login_timme' => 'datetime',
'info' => 'array'
];
}
使用示例
//
$user = new User;
$user->status = '1';
$user->score = '90.50';
$user->birthday = '2015/5/1';
$user->info = ['a'=>1,'b'=>2];
$user->save();
var_dump($user->status); // int 1
var_dump($user->score); // float 90.5;
var_dump($user->birthday); // string '2015-05-01 00:00:00'
var_dump($user->info);// array (size=2) 'a' => int 1 'b' => int 2
注意: 如果制定為時間戳類型(timestamp)的話芙盘,該字段會在寫入的時候自動調(diào)用strtotime函數(shù)生成對應(yīng)的時間戳驯用,輸出是自動使用dateFormat格式化時間戳,默認(rèn)格式為Y:m:d H:i:s,如果想要改變輸出格式儒老,可以如下:
class User extends Model{
protected $dataFormat = 'Y/m/d';
protected $type = [
'status' => 'integer',
'score' => 'float',
'birthday' => 'timestemp'//時間戳格式
];
}
或者如下:
class User extends Model{
protected $type = [
'status' => 'integer',
'socre' => 'float',
'birthday' => 'timestemp:Y/m/d'//寫入時間戳蝴乔,讀取按照Y/m/d的格式來格式化輸出。
];
}
原稿:http://blog.csdn.net/qq_20678155/article/details/68926487
作者:CSDN博主:輘酆