## 模型定義
定義一個模型類很簡單,下面是一個最簡單的`User`模型:
~~~
<?php
namespace app\model;
use think\Model;
class User extends Model
{
}
~~~
>[info] 請確保你已經在數據庫配置文件中配置了數據庫連接信息,如不清楚請參考數據庫一章
模型會自動對應數據表,模型類的命名規則是除去表前綴的數據表名稱,采用駝峰法命名,并且首字母大寫,例如:
| 模型名 | 約定對應數據表(假設數據庫的前綴定義是 `think_`) |
|-----|-----|
| User | think_user |
| UserType | think_user_type |
如果你的規則和上面的系統約定不符合,那么需要設置模型類的數據表名稱`table`屬性,以確保能夠找到對應的數據表。
>[danger] 模型自動對應的數據表名稱都是遵循小寫+下劃線規范,如果你的表名有大寫的情況,必須通過設置模型的`table`屬性。
如果你希望給模型類添加后綴,必須要設置`name`屬性或者`table`屬性。
~~~
<?php
namespace app\model;
use think\Model;
class UserModel extends Model
{
protected $name = 'user';
}
~~~
## 模型設置
默認主鍵為`id`,如果你沒有使用`id`作為主鍵名,需要在模型中設置屬性:
~~~
<?php
namespace app\model;
use think\Model;
class User extends Model
{
protected $pk = 'uid';
}
~~~
如果你想指定數據表甚至數據庫連接的話,可以使用:
~~~
<?php
namespace app\model;
use think\Model;
class User extends Model
{
// 設置當前模型對應的完整數據表名稱
protected $table = 'think_user';
// 設置當前模型的數據庫連接
protected $connection = 'db_config';
}
~~~
>[danger] `connection`屬性使用用配置參數名(需要在數據庫配置文件中的`connections`參數中添加對應標識)。
常用的模型設置屬性包括(以下屬性都不是必須設置):
屬性|描述
---|---
name|模型名(相當于不帶數據表前后綴的表名,默認為當前模型類名)
table|數據表名(默認自動獲取)
suffix|數據表后綴(默認為空)
pk|主鍵名(默認為`id`)
connection|數據庫連接(默認讀取數據庫配置)
field|模型允許寫入的字段列表(數組)
schema|模型對應數據表字段及類型(數組)
type|模型需要自動轉換的字段及類型(數組)
strict|是否嚴格區分字段大小寫(默認為true)
disuse|數據表廢棄字段(數組)
>[danger] 模型不支持對數據表的前綴單獨設置,并且也不推薦使用數據表的前綴設計,應該用不同的庫區分。當你的數據表沒有前綴的時候,`name`和`table`屬性的定義是沒有區別的,定義任何一個即可。
## 字段定義
模型的數據字段和對應數據表的字段是對應的,默認會自動獲取(包括字段類型),但自動獲取會導致增加一次查詢,因此你可以在模型中明確定義字段信息避免多一次查詢的開銷。
~~~
<?php
namespace app\model;
use think\Model;
class User extends Model
{
// 設置字段信息
protected $schema = [
'id' => 'int',
'name' => 'string',
'status' => 'int',
'score' => 'float',
'create_time' => 'datetime',
'update_time' => 'datetime',
];
}
~~~
> 字段類型的定義可以使用PHP類型或者數據庫的字段類型都可以,字段類型定義的作用主要用于查詢的參數自動綁定類型。
>[danger] 時間字段盡量采用實際的數據庫類型定義,便于時間查詢的字段自動識別。如果是`json`類型直接定義為`json`即可。
如果在ThinkPHP`6.0+`中使用的話,沒有定義`schema`屬性的話,可以在部署完成后運行如下指令。
~~~cmd
php think optimize:schema
~~~
運行后會自動生成數據表的字段信息緩存。使用命令行緩存的優勢是Db類的查詢仍然有效。
## 字段類型
`schema`屬性一旦定義,就必須定義完整的數據表字段類型。
如果你只希望對某個字段定義需要自動轉換的類型,可以使用`type`屬性,例如:
~~~
<?php
namespace app\model;
use think\Model;
class User extends Model
{
// 設置字段自動轉換類型
protected $type = [
'score' => 'float',
];
}
~~~
> `type`屬性定義的不一定是實際的字段,也有可能是你的字段別名。
## 廢棄字段
如果因為歷史遺留問題 ,你的數據表存在很多的廢棄字段,你可以在模型里面定義這些不再使用的字段。
~~~
<?php
namespace app\model;
use think\Model;
class User extends Model
{
// 設置廢棄字段
protected $disuse = [ 'status', 'type' ];
}
~~~
在查詢和寫入的時候會忽略定義的`status`和`type`廢棄字段。
## 獲取數據
在模型外部獲取數據的方法如下
~~~
$user = User::find(1);
echo $user->create_time;
echo $user->name;
~~~
由于模型類實現了`ArrayAccess`接口,所以可以當成數組使用。
~~~
$user = User::find(1);
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);
```
或者使用
```
$user = new User();
$data['name'] = 'thinkphp';
$data['score'] = 100;
$user->data($data);
```
## 字段大小寫
默認情況下,你的模型數據名稱和數據表字段應該保持嚴格一致,也就是說區分大小寫。
~~~
$user = User::find(1);
echo $user->create_time; // 正確
echo $user->createTime; // 錯誤
~~~
>[danger] 嚴格區分字段大小寫的情況下,如果你的數據表字段是大寫,模型獲取的時候也必須使用大寫。
如果你希望在獲取模型數據的時候不區分大小寫(前提是數據表的字段命名必須規范,即小寫+下劃線),可以設置模型的`strict`屬性。
~~~
<?php
namespace app\model;
use think\Model;
class User extends Model
{
// 模型數據不區分大小寫
protected $strict = false,
}
~~~
你現在可以使用
~~~
$user = User::find(1);
// 下面兩種方式都有效
echo $user->createTime;
echo $user->create_time;
~~~
前提是你實際的數據表字段必須符合規范,采用小寫和下劃線設計,例如這里必須是`create_time`。
## 模型數據轉駝峰
`V2.0.34+`版本開始,可以設置`convertNameToCamel`屬性使得模型數據返回駝峰方式命名(前提也是數據表的字段命名必須規范,即小寫+下劃線)。
~~~
<?php
namespace app\model;
use think\Model;
class User extends Model
{
// 數據轉換為駝峰命名
protected $convertNameToCamel = true,
}
~~~
然后在模型輸出的時候可以直接使用駝峰命名的方式獲取。
~~~
$user = User::find(1);
$data = $user->toArray();
echo $data['createTime']; // 正確
echo $user['create_time']; // 錯誤
~~~
## 模型初始化
模型支持初始化,只需要定義`init`方法,例如:
~~~
<?php
namespace app\model;
use think\Model;
class User extends Model
{
// 模型初始化
protected static function init()
{
//TODO:初始化內容
}
}
~~~
>[danger] `init`必須是靜態方法,并且只在第一次實例化的時候執行,并且只會執行一次
## 模型操作
> 在模型中除了可以調用數據庫類的方法之外(換句話說,**數據庫的所有查詢構造器方法模型中都可以支持**),可以定義自己的方法,所以也可以把模型看成是數據庫的增強版。
模型的操作方法無需和數據庫查詢一樣調用必須首先調用`table`或者`name`方法,因為模型會按照規則自動匹配對應的數據表,例如:
~~~
Db::name('user')->where('id','>',10)->select();
~~~
改成模型操作的話就變成
~~~
User::where('id','>',10)->select();
~~~
雖然看起來是相同的查詢條件,但一個最明顯的區別是**查詢結果的類型**不同。第一種方式的查詢結果是一個普通的數據集對象,而第二種方式的查詢結果是包含了模型數據集對象。
模型操作和數據庫操作的另外一個顯著區別是模型支持包括獲取器、修改器、自動時間寫入在內的一系列自動化操作和事件,簡化了數據的存取操作,但隨之而來的是性能有所下降(其實并沒下降,而是自動幫你處理了一些原本需要手動處理的操作),后面會逐步領略到模型的這些特色功能。
## 動態切換后綴
數據表后綴屬性,可以用于多語言或者數據分表的模型查詢,省去為多個相同結構的表定義多個模型的麻煩。
默認的數據表后綴可以在模型類里面直接定義`suffix`屬性。
~~~
<?php
namespace app\model;
use think\Model;
class Blog extends Model
{
// 定義默認的表后綴(默認查詢中文數據)
protected $suffix = _cn';
}
~~~
>[danger] 你在模型里面定義的`name`和`table`屬性無需包含后綴定義
模型提供了動態切換方法`suffix`和`setSuffix`,例如:
```
// suffix方法用于靜態查詢
$blog = Blog::suffix('_en')->find();
$blog->name = 'test';
$blog->save();
// setSuffix用于動態設置
$blog = new Blog($data);
$blog->setSuffix('_en')->save();
```
## 模型方法依賴注入
如果你需要對模型的方法支持依賴注入,可以把模型的方法改成閉包的方式,例如,你需要對獲取器方法增加依賴注入
```
public function getTestFieldAttr($value,$data) {
return $this->invoke(function(Request $request) use($value,$data) {
return $data['name'] . $request->action();
};
}
```
不僅僅是獲取器方法,在任何需要依賴注入的方法都可以改造為調用`invoke`方法的方式,`invoke`方法第二個參數用于傳入需要調用的(數組)參數。
如果你需要直接調用某個已經定義的模型方法(假設已經使用了依賴注入),可以使用
```
protected function bar($name, Request $request) {
// ...
}
protected function invokeCall(){
return $this->invoke('bar',['think']);
}
```
- 簡介
- 數據庫配置
- 分布式數據庫
- 查詢構造器
- 查詢數據
- 新增數據
- 更新數據
- 刪除數據
- 鏈式操作
- Where
- Table
- Alias
- Field
- Strict
- Limit
- Page
- Order
- Group
- Having
- Join
- Union
- Distinct
- Lock
- Cache
- Comment
- FetchSql
- Force
- Partition
- Replace
- FailException
- Extra
- Duplicate
- Sequence
- Procedure
- View
- 聚合查詢
- 分頁查詢
- 時間查詢
- 高級查詢
- 子查詢
- 原生查詢
- 事務操作
- 存儲過程
- 查詢事件
- JSON字段
- 模型
- 定義
- 新增
- 更新
- 刪除
- 查詢
- 查詢范圍
- 只讀字段
- JSON字段
- 自動時間寫入
- 獲取器
- 修改器
- 搜索器
- 類型轉換
- 模型輸出
- 模型事件
- 虛擬模型
- 關聯
- 一對一關聯
- 一對多關聯
- 遠程一對多
- 遠程一對一
- 多對多關聯
- 多態一對多
- 多態一對一
- 關聯預載入
- 關聯統計
- 關聯輸出
- SQL監聽
- 緩存機制
- 字段緩存
- 查詢緩存
- 擴展
- 自定義查詢類
- 自定義數據庫驅動