5.0的數據庫抽象訪問層(我們后面用Db類表示)和模型是一個整體,共同完成了ThinkPHP5.0的ORM(對象關系映射)。
Db和模型最明顯的一個區別就是Db查詢返回的數據類型為數組(對于一個沒有業務邏輯的數據而言,數組已經足夠),而模型的查詢返回類型的是模型對象實例。
Db類已經非常的強大,但缺點是:
* 不支持ActiveRecord實現;
* 缺乏靈活的事件機制;
* 數據自動處理能力弱;
* 數據關聯操作繁瑣并且不直觀;
* 不能單獨封裝業務邏輯;
還有很多...當然,原因并不是否定Db類的實現,因為Db和模型本來就是一個整體,只是各自的職責和分工不同,如果沒有Db類的基石,模型也只是建在沙灘上的城堡罷了。
因此Db和模型的存在只是ThinkPHP5.0架構設計中的職責和定位不同,Db負責的只是數據(表)訪問,模型負責的是業務數據和業務邏輯。
如果你用框架只是用來管理一些數據的CURD而沒有業務需要(其實本質上來說任何的系統都是CURD,業務邏輯都是抽象和封裝出來的,這是設計層面的問題了),那么Db類也許已經夠用了,但是作為一個業務系統或者平臺(無論是WEB還是API),通常每個數據表就對應了一個業務模型對象,甚至存在和其它業務模型的混合和關聯邏輯。
舉個用戶表的例子,用戶登錄這樣一個業務邏輯其實包含了很多的關聯操作,你得檢查用戶賬號是否正常,用戶名和密碼是否正確,然后記錄用戶的最后登錄時間和IP(如果IP所在區域不符有些系統還需要給用戶發郵件提醒),還要給用戶增加積分,甚至可能還需要檢查用戶的權限,那么Db類就顯得吃力了,這其實也是數組存儲結構和對象存儲設計的差異,業務越復雜,這種差異越明顯。
當然,模型層可以分的更細,把數據模型和邏輯模型,甚至服務模型分開,這個暫時就不在目前的討論范疇了,只不過把模型層的職責和分工更細化。
想要掌握模型,必須明白和理解下面幾個原則:
1. 模型和數據庫層的定位和職責不同;
2. 不要因為性能而放棄使用模型,那是得不償失的;
3. **用面向對象的方式來使用和設計模型;**
4. 模型的數據底層操作仍然是數據庫抽象訪問層,而且是自動的;
模型設計基于數據訪問層之上,并作了更高層次的封裝,實現了Db類本身不支持的功能,或者簡化了原本使用Db類的復雜操作。從查詢操作的角度來看,可以理解為**Db類是數據表的查詢構造器,而模型是業務模型的查詢構造器**,其實都屬于查詢構造器的范疇。
在控制器中永遠調用的是模型類,然后在模型類中封裝業務邏輯方法和數據處理,完成業務操作。**對控制器來說,模型就是一個業務邏輯接口**,并且善于運用依賴注入機制來綁定模型對業務操作會帶來極大的便利。
模型定義階段要達成的目的:
1. 定義數據表(默認就是模型類名)
2. 定義數據表主鍵(默認會自動獲取)
3. 定義數據庫連接(默認使用數據庫配置)
4. 定義數據處理邏輯(包括屬性和方法)
5. 定義業務邏輯(方法)
大多數情況下,數據表和數據庫連接是不需要定義的,數據處理邏輯和業務邏輯才是模型定義的重點,如果你發現你的大多數模型類都是什么都沒定義,那么就要思考下哪里出問題了,為什么你的模型成了形式和擺設。是沒業務需要還是職責分工有問題了?
一個模型并不總是對應一個數據表(例如關聯模型和聚合模型),但大多數情況下對應的是一個數據表,默認的對應關系是:模型類的名稱(注意不一定是類名,后面會解釋)轉換為小寫和下劃線就是對應的數據表:
|模型名 |對應數據表|
| --- | --- |
|User|user |
|UserType|user_type |
如果你的數據庫配置定義了前綴(假設數據庫的前綴定義是 think_),那么對應關系就是:
|模型名|對應數據表|
| --- | --- |
|User |think_user|
|UserType|think_user_type|
模型的設計允許給單獨指定數據庫連接,也就說你可以將不同的數據庫的表進行統一的管理,對于跨數據庫的應用尤其有用,對于跨庫的相同表名,我們可以建立不同名稱的模型或者放入不同的命名空間來解決。
指定模型的單獨數據庫連接方法如下:
~~~
<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
protected $name = 'user_info';
protected $connection = 'db_config';
}
~~~
和Db類的connect方法一樣,模型類的connection屬性允許使用數組、字符串以及配置參數的方式定義,這里使用配置參數(在應用或者模塊的配置文件中單獨配置db_config參數)的方式,避免在模型里面寫死數據庫連接信息,全部交給配置文件去統一處理。
如果connection屬性使用數組方式配置,會和數據庫配置文件中的參數合并,因此你只需要定義有區別的參數,而無需定義全部的數據庫參數。
模型調用
模型支持實例化調用和靜態調用(主要是查詢,查詢后會返回一個模型對象實例)。
~~~
// 實例化User模型
$user = new \app\index\model\User();
// 直接靜態查詢
$user = \app\index\model\User::get(1);
~~~
如果你覺得每次引入比較麻煩,系統還提供了一個助手函數幫助你快速實例化模型類而不必每次引入模型類。
你可以在任何地方使用
~~~
$user = model('User');
~~~
實例化User模型類,并且model函數采用單例實現,多次調用不會重復實例化。
我們還是建議使用use方式引入模型類后操作,因為助手函數并不支持模型的靜態調用,這個后面我們還會詳細說明。