## 模型定義
快速生成模型:
~~~
$php think make:model index@BlogModel
$php think make:model index@UserModel
~~~
模型實例:
~~~
<?php
namespace app\model;
use think\Model;
class User extends Model
{
//自定義模型名
protected $name = 'user';
//自定義主鍵,可以是數組
protected $pk = 'uuid';
// 自定義表名稱
protected $table = 'think_user';
// 自定義數據庫連接
protected $connection = 'db_config';
// 開啟自動寫入時間戳字段,支持timestamp/datetime/int/false/true
protected $autoWriteTimestamp = 'datetime';
// 以下兩行如果不寫,默認為:create_time/update_time
protected $createTime = 'create_at';
protected $updateTime = 'update_at';
}
~~~
## 模型的屬性
| 屬性 | 描述 |
| --- | --- |
| name | 模型名(相當于不帶數據表前后綴的表名,默認為當前模型類名) |
| table | 數據表名(默認自動獲取) |
| suffix | 數據表后綴(默認為空) |
| pk | 主鍵名(默認為`id`) |
| connection | 數據庫連接(默認讀取數據庫配置) |
| query | 模型使用的查詢類名稱 |
| field | 模型允許寫入的字段列表(數組) |
| schema | 模型對應數據表字段及類型 |
| type | 模型需要自動轉換的字段及類型 |
| strict | 是否嚴格區分字段大小寫(默認為true) |
| disuse | 數據表廢棄字段(數組) |
## 模型初始化
~~~
<?php
namespace app\model;
use think\Model;
class User extends Model
{
// `init`必須是靜態方法,只在第一次實例化的時候執行一次
protected static function init()
{
//TODO:初始化內容
}
}
~~~
> 模型支持包括獲取器、修改器、自動時間寫入在內的一系列自動化操作和事件,簡化了數據的存取操作。
## 模型操作
> 模型是數據庫的增強版。
數據庫操作:
~~~
Db::name('user')->where('id','>',10)->select();
~~~
改成模型操作:
~~~
/* 忽略了表名等模型中已包含的信息 */
User::where('id','>',10)->select();
~~~
第一種方式的查詢結果是一個二維數組,而第二種方式的查詢結果是包含了模型(集合)的數據集。不過,在大多數情況下,這兩種返回類型的使用方式并無明顯區別。
## 獲取數據
在模型外部:
~~~
$user = User::find(1);
echo $user->create_time;
echo $user->name;
//使用了 `ArrayAccess` 接口
echo $user['create_time'];
echo $user['name'];
~~~
在模型內部:
~~~
$user = $this->find(1);
echo $user->getAttr('create_time');
echo $user->getAttr('name');
~~~
## 模型賦值
~~~
$user = new User();
$user->name = 'thinkphp';
$user->score = 100;
~~~
該方式賦值會自動執行模型的修改器,如果不希望執行修改器操作,可以使用:
~~~
$data['name'] = 'thinkphp';
$data['score'] = 100;
$user = new User($data);
~~~
`data`方法支持使用修改器
~~~
$user = new User();
$data['name'] = 'thinkphp';
$data['score'] = 100;
$user->data($data, true);
~~~
## 添加一條數據
第一種是實例化模型對象后賦值并保存:
~~~
$user = new User;
$user->name = 'thinkphp';
$user->email = 'thinkphp@qq.com';
$user->save();
~~~
> `save`方法成功會返回`true`,一旦有錯誤就會拋出異常,無需判斷返回值。
也可以直接傳入數據到`save`方法批量賦值:
~~~
$user = new User;
$user->save([
'name' => 'thinkphp',
'email' => 'thinkphp@qq.com'
]);
~~~
默認只會寫入數據表已有的字段。如果希望指定某些字段寫入,可以使用:
~~~
$user = new User;
// post數組中只有name和email字段會寫入
$user->allowField(['name','email'])->save($_POST);
~~~
最佳的建議是模型數據賦值之前就進行數據過濾,例如:
~~~
$user = new User;
// 過濾post數組中的非數據表字段數據
$data = Request::only(['name','email']);
$user->save($data);
~~~
`save`方法新增數據返回的是寫入的記錄數(通常是`1`)。
> 不要在同一個實例里面多次新增數據,如果確實需要多次新增,可以使用后面的靜態方法處理。
## `Replace`寫入
~~~
$user = new User;
$user->name = 'thinkphp';
$user->email = 'thinkphp@qq.com';
$user->replace()->save();
~~~
## 獲取自增ID
如果要獲取新增數據的自增ID,可以使用下面的方式:
~~~
$user = new User;
$user->name = 'thinkphp';
$user->email = 'thinkphp@qq.com';
$user->save();
echo $user->id; // 獲取自增ID,或者相應的主鍵pk
~~~
## 批量增加數據
支持批量新增,可以使用:
~~~
$user = new User;
$list = [
['name'=>'thinkphp','email'=>'thinkphp@qq.com'],
['name'=>'onethink','email'=>'onethink@qq.com']
];
$user->saveAll($list);
~~~
> saveAll方法新增數據返回的是包含新增模型(帶自增ID)的數據集對象。
`saveAll`方法能自動識別數據是需要新增還是更新操作,當數據中存在主鍵的時候會認為是更新操作。
## 靜態方法
還可以直接靜態調用`create`方法創建并寫入:
~~~
$user = User::create([
'name' => 'thinkphp',
'email' => 'thinkphp@qq.com'
]);
echo $user->name;
echo $user->email;
echo $user->id; // 獲取自增ID
~~~
> 和`save`方法不同的是,`create`方法返回的是當前模型的對象實例。
`create`方法默認會過濾不是數據表的字段信息,可以在第二個參數傳入允許寫入的字段列表,例如:
~~~
// 只允許寫入name和email字段的數據
$user = User::create([
'name' => 'thinkphp',
'email' => 'thinkphp@qq.com'
], ['name', 'email']);
echo $user->name;
echo $user->email;
echo $user->id; // 獲取自增ID
~~~
支持`replace`操作,使用下面的方法:
~~~
$user = User::create([
'name' => 'thinkphp',
'email' => 'thinkphp@qq.com'
], ['name','email'], true);
~~~
## 建議的新增方式
新增數據的最佳實踐原則:使用`create`方法新增數據,使用`saveAll`批量新增數據。
## 查找并更新
在取出數據后,更改字段內容后使用`save`方法更新數據。**這種方式是最佳的更新方式**。
~~~
$user = User::find(1);
$user->email = 'thinkphp@qq.com';
$user->save();
~~~
> `save`方法成功返回`true`,并只有當`before_update`事件返回`false`的時候返回`false`,有錯誤則會拋出異常。
如果要執行SQL函數更新,可以使用下面的方法。
~~~
$user = User::find(1);
$user->score = Db::raw('score+1');
$user->save();
~~~
## 字段過濾
默認情況下會過濾非數據表字段的數據,如果你通過外部提交賦值給模型,并且希望指定某些字段寫入,可以使用:
~~~
$user = User::find(1);
// post數組中只有name和email字段會寫入
$user->allowField(['name', 'email'])->save($_POST);
~~~
最佳用法是在傳入模型數據之前就進行過濾,例如:
~~~
$user = User::find(1);
// post數組中只有name和email字段會寫入
$data = Request::only(['name','email']);
$user->save($data);
~~~
## 批量更新數據
可以使用`saveAll`方法批量更新數據,只需要在批量更新的數據中包含主鍵即可,例如:
~~~
$user = new User;
$list = [
['id'=>1, 'name'=>'thinkphp', 'email'=>'thinkphp@qq.com'],
['id'=>2, 'name'=>'onethink', 'email'=>'onethink@qq.com']
];
$user->saveAll($list);
~~~
批量更新方法返回的是一個數據集對象。
> 批量更新僅能根據主鍵值進行更新,其它情況請自行處理。
## 直接更新(靜態方法)
使用模型的靜態`update`方法更新:
~~~
User::update(['name' => 'thinkphp'], ['id' => 1]);
~~~
> 模型的`update`方法返回模型的對象實例
如果你的第一個參數中包含主鍵數據,可以無需傳入第二個參數(更新條件)
~~~
User::update(['name' => 'thinkphp', 'id' => 1]);
~~~
如果你需要只允許更新指定字段,可以使用
~~~
User::update(['name' => 'thinkphp', 'email' => 'thinkphp@qq.com'], ['id' => 1], ['name']);
~~~
上面的代碼只會更新`name`字段的數據。
## 刪除當前模型
刪除模型數據,可以在查詢后調用`delete`方法。
~~~
$user = User::find(1);
$user->delete();
~~~
> `delete`方法返回布爾值。
## 根據主鍵刪除
或者直接調用靜態方法(根據主鍵刪除)
~~~
User::destroy(1);
// 支持批量刪除多個數據
User::destroy([1,2,3]);
~~~
> 當`destroy`方法傳入空值(包括空字符串和空數組)的時候不會做任何的數據刪除操作,但傳入0則是有效的。
## 條件刪除
還支持使用閉包刪除,例如:
~~~
User::destroy(function($query){
$query->where('id','>',10);
});
~~~
或者通過數據庫類的查詢條件刪除
~~~
User::where('id','>',10)->delete();
~~~
> 直接調用數據庫的`delete`方法的話無法調用模型事件。
## 關于刪除的建議
> 刪除的最佳實踐原則是:如果刪除當前模型數據,用`delete`方法,如果需要直接刪除數據,使用`destroy`靜態方法。
## 獲取單個數據
獲取單個數據的方法包括:
~~~
// 取出主鍵為1的數據
$user = User::find(1);
echo $user->name;
// 使用查詢構造器查詢滿足條件的數據
$user = User::where('name', 'thinkphp')->find();
echo $user->name;
~~~
模型使用`find`方法查詢,如果數據不存在返回`Null`,否則返回當前模型的對象實例。如果希望查詢數據不存在則返回一個空模型,可以使用。
~~~
$user = User::findOrEmpty(1);
~~~
你可以用`isEmpty`方法來判斷當前是否為一個空模型。
~~~
$user = User::where('name', 'thinkphp')->findOrEmpty();
if (!$user->isEmpty()) {
echo $user->name;
}
~~~
> 如果你是在模型內部獲取數據,使用`$this->getAttr('name')`。
## 獲取多個數據
取出多個數據:
~~~
// 根據主鍵獲取多個數據
$list = User::select([1,2,3]);
// 對數據集進行遍歷操作
foreach($list as $key=>$user){
echo $user->name;
}
~~~
要更多的查詢支持,一樣可以使用查詢構造器:
~~~
// 使用查詢構造器查詢
$list = User::where('status', 1)->limit(3)->order('id', 'asc')->select();
foreach($list as $key=>$user){
echo $user->name;
}
~~~
> 查詢構造器方式的查詢可以支持更多的連貫操作,包括排序、數量限制等。
## 使用查詢構造器
~~~
User::where('id',10)->find();
User::where('status',1)->order('id desc')->select();
User::where('status',1)->limit(10)->select();
~~~
使用查詢構造器直接使用靜態方法調用即可,無需先實例化模型。
### 獲取某個字段或者某個列的值
~~~
// 獲取某個用戶的積分
User::where('id',10)->value('score');
// 獲取某個列的所有值
User::where('status',1)->column('name');
// 以id為索引
User::where('status',1)->column('name','id');
~~~
> `value`和`column`方法返回的不再是一個模型對象實例,而是純粹的值或者某個列的數組。
### 動態查詢
支持數據庫的動態查詢方法,例如:
~~~
// 根據name字段查詢用戶
$user = User::getByName('thinkphp');
// 根據email字段查詢用戶
$user = User::getByEmail('thinkphp@qq.com');
~~~
### 聚合查詢
同樣在模型中也可以調用數據庫的聚合方法查詢,例如:
~~~
User::count();
User::where('status','>',0)->count();
User::where('status',1)->avg('score');
User::max('score');
~~~
注意,如果你的字段不是數字類型,是使用`max`/`min`的時候,需要加上第二個參數:`User::max('name', false);`。
## 關于查詢的建議
> 模型查詢的最佳實踐原則是:在模型外部使用靜態方法進行查詢,內部使用動態方法查詢,包括使用數據庫的查詢構造器。
- 搭建ThinkPHP6的開發環境
- 配置ThinkPHP6
- 必要的基礎知識(basic)
- MVC開發模式
- 控制器(controller)
- 數據庫(database)
- 模型(model)
- 模型關聯(relation)
- 視圖(view)
- Session
- Cookie
- 緩存(cache)
- 上傳(upload)
- 驗證器(validate)
- 驗證碼(captcha)
- 命令行(command)
- 服務器部署(deploy)
- 數據備份(backup)
- 數據同步(synchronization)
- 訂閱服務(subscribe)
- PHP 易混淆知識點
- 助手函數
- MySQL規范
- Redis 規范
- office插件 phpoffice
- 拼音插件 pinyin
- 日期插件 datetime
- 消息插件 amqp
- 產品部署環境的搭建
- PDF 等雜項處理
- 文件上傳
- 常用擴展
- flc/dysms
- 使用示例 ①
- 使用示例 ②
- qiniu/php-sdk
- 簡介
- 使用示例
- 使用示例 2 ②
- liliuwei/thinkphp-jump
- 擴展介紹
- 下載擴展
- 使用方法
- topthink/think-captcha
- 安裝擴展
- 驗證碼顯示
- 更換驗證碼
- 驗證碼校驗
- 驗證碼配置
- 自定義驗證碼
- phpoffice/phpspreadsheet
- 數據寫入表格
- 讀取表格數據
- topthink/think-queue
- 安裝
- 自定義函數
- 任務類
- 帶有日志的任務類