[TOC]
## 1 新模型解讀
TP5RC3中重點更新了Model的功能。
新的Model是**TP5設計目標——為API開發而設計**的核心功能。
新的Model與以前版本的功能完全不同,下面進行分析。
## 2 新模型源代碼
### 2-1 Model類的聲明
~~~
;聲明Model為抽象類并實現序列化接口和數組訪問接口功能
abstract class Model implements \JsonSerializable, \ArrayAccess
{}
~~~
### 2-2 成員變量
~~~
;數據庫模型數組,數據庫連接配置,模型操作的表,回調事件
private static $links = [];
protected static $connection = [];
protected static $table;
protected static $event = [];
;模型操作表的主鍵,數據表操作的錯誤信息,自定義模型名稱,字段驗證規則
protected $pk;
protected $error;
protected $name;
protected $validate;
;字段屬性信息數組,待操作數據數組,緩存數據數組,修改字段數組
protected $field = [];
protected $data = [];
protected $cache = [];
protected $change = [];
;自動完成數組,新增自動完成數組,更新自動完成數組,自動寫入時間戳數組,時間戳默認格式
protected $auto = [];
protected $insert = [];
protected $update = [];
protected $autoTimeField = ['create_time', 'update_time', 'delete_time'];
protected $dateFormat = 'Y-m-d H:i:s';
;字段類型或格式轉換數組,是否為更新操作,模型對應關聯對象,當前模型的父模型,模型實例數組
protected $type = [];
protected $isUpdate = false;
protected $relation;
protected $parent;
protected static $initialized = [];
~~~
### 2-3 public成員方法
#### 1 __construct() 創建模型實例
~~~
public function __construct($data = [])
~~~
> $data 模型的數據參數
~~~
;創建對象傳入$data參數
$user = new User(['name'=>'thinkphp','email'=>'thinkphp@qq.com']);
$user->save();
;實例化模型,設置$this->data['name']為'thinkphp',調用save()更新數據
$user = new User;
$user->name= 'thinkphp';
$user->save();
~~~
#### 2 data() 設置數據對象值
~~~
public function data($data = '')
~~~
> $data 操作數據參數
~~~
;設置模型的$data
$user = new User;
$user->data(['name'=>'thinkphp','email'=>'thinkphp@qq.com']);
$user->save();
~~~
#### 3 getData() 獲取對象原始數據
~~~
public function getData($name = '')
~~~
> $name 數據的鍵名
在定義了getXXAttr()時使用獲取原始數據
#### 4 toArray() 將數據轉換為數組
~~~
public function toArray()
~~~
#### 5 getPk() 獲取模型的主鍵信息
~~~
public function getPk($table = '')
~~~
#### 6 save() 更新數據到數據庫
~~~
public function save($data = [], $where = [], $getInsertId = true)
~~~
> $data 插入的數據
> $where 更新條件
> $getInsertId 是否獲取自增主鍵
~~~
;傳入數據更新
$user = new User;
$user->save(['name' => 'thinkphp'],['id' => 1]);
;使用模型數據更新
$user = User::get(1);
$user->name = 'thinkphp';
$user->save();
;使用閉包實現復雜條件
$user = new User;
$user->save(['name' => 'thinkphp'],function($query){
// 更新status值為1 并且id大于10的數據
$query->where('status',1')->where('id','>',10);
});
~~~
#### 7 saveAll() 修改多個數據到數據庫
~~~
public function saveAll($dataSet)
~~~
> $dataSet 待插入數據集合
#### 8 allowField() 設置運行更新的字段
~~~
public function allowField($field)
~~~
#### 9 isUpdate() 檢查當前操作是否為更新操作
~~~
public function isUpdate($update = true)
~~~
#### 10 delete() 對數據進行刪除處理
~~~
public function delete()
~~~
~~~
;刪除模型數據
$user = User::get(1);
$user->delete();
~~~
#### 11 auto() 設置自動完成字段,在autoCompleteData中檢查
~~~
public function auto($fields)
~~~
~~~
class User extends Model{
protected $auto = [ 'update_time'];
protected $insert = [
'create_time','name','status'=>1
];
protected $update = ['name'];
protected function setNameAttr($value){
return strtolower($value);
}
}
$user = new User;
$user->name = 'ThinkPHP';
$user->save();
echo $user->name; // thinkphp
echo $user->create_time; // 14601053899
~~~
#### 12 validate() 設置自動驗證規則
~~~
public function validate($rule = true, $msg = [])
~~~
> $rule 驗證規則
> $msg 提示信息
使用見 驗證類分析
#### 13 validateData() 對當前data進行驗證處理
~~~
public function validateData()
~~~
#### 14 getError() 獲取操作錯誤信息
~~~
public function getError()
~~~
#### 15 event() 注冊事件回調接口
~~~
public static function event($event, $callback, $override = false)
~~~
>$event 事件名稱
> 支持的事件類型,在模型操作過程中會進行回調before_delete、after_delete、before_write、after_write、before_update、after_update、before_insert、after_insert
> $callback 事件回調接口
~~~
;注冊before_insert事件,
User::event('before_insert',function($user){
if($user->status != 1){
return false;
}
});
~~~
#### 16 create() 寫入數據
~~~
public static function create($data = [])
~~~
> $data 待寫入數據
~~~
User::create(['name'=>'thinkphp','email'=>'thinkphp@qq.com']);
~~~
#### 17 update() 更新數據
~~~
public static function update($data = [], $where = [])
~~~
> $data 待更新數據
> $where 更新條件
~~~
User::where('id',1)->update(['name' => 'thinkphp']);
~~~
#### 18 get() 數據查詢
~~~
public static function get($data = '', $with = [], $cache = false)
~~~
~~~
$user = User::get(1);
echo $user->name;
// 使用閉包查詢
$user = User::get(function($query){
$query->where('name','thinkphp');
});
echo $user->name;
~~~
#### 19 all() 查詢多個記錄
~~~
public static function all($data = [], $with = [], $cache = false)
~~~
~~~
// 根據主鍵獲取多個數據
$list = User::all('1,2,3');
// 或者使用數組
$list = User::all([1,2,3]);
foreach($list as $key=>$user){
echo $user->name;
}
// 使用閉包查詢
$list = User::all(function($query){
$query->where('status',1)->limit(3)->order('id','asc');
});
foreach($list as $key=>$user){
echo $user->name;
}
~~~
#### 20 destroy() 刪除記錄
~~~
public static function destroy($data)
~~~
~~~
User::destroy(1);
// 支持批量刪除多個數據
User::destroy('1,2,3');
// 或者
User::destroy([1,2,3]);
;閉包刪除
User::destroy(function($query){
$query->where('id','>',10);
});
~~~
#### 21 scope() 設置命名范圍
~~~
public static function scope($name, $params = [])
~~~
~~~
class User extends Model{
public function scopeThinkphp($query){
$query->where('name','thinkphp')->field('id,name');
}
public function scopeAge($query){
$query->where('age','>',20)->limit(10);
}
}
// 查找name為thinkphp的用戶
User::scope('thinkphp')->get();
// 查找年齡大于20的10個用戶
User::scope('age')->all();
// 查找name為thinkphp的用戶并且年齡大于20的10個用戶
User::scope('thinkphp,age')->all();
User::scope(function($query){
$query->where('age','>',20)->limit(10);
})->all();
$user = new User;
// 查找name為thinkphp的用戶
$user->thinkphp()->get();
// 查找年齡大于20的10個用戶
$user->age()->all();
// 查找name為thinkphp的用戶并且年齡大于20的10個用戶
$user->thinkphp()->age()->all();
~~~
#### 22 has() hasWhere() 在關聯中進行查找
~~~
public static function has($relation, $operator = '>=', $count = 1, $id = '*')
public static function hasWhere($relation, $where = [])
~~~
#### 23 relationQuery() 執行關聯查詢
~~~
public function relationQuery($relations)
~~~
#### 24 getRelationInfo() 獲取關聯信息
~~~
public function getRelationInfo($name = '')
~~~
#### 25 eagerlyResultSet() eagerlyResult()預載入關聯查詢
~~~
public function eagerlyResultSet($resultSet, $relation)
public function eagerlyResult($result, $relation)
~~~
#### 26 hasOne() belongsTo() hasMany() belongsToMany() 關聯定義
~~~
;一對一關聯
public function hasOne($model, $foreignKey = '', $localKey = '')
;相對關聯
public function belongsTo($model, $foreignKey = '', $otherKey = '')
;一對多關聯
public function hasMany($model, $foreignKey = '', $localKey = '')
;多對多關聯
public function belongsToMany($model, $table = '', $localKey = '', $foreignKey = '')
~~~
~~~
;一對一關聯
class User extends Model {
public function profile()
{
return $this->hasOne('Profile');
}
}
$user = User::find(1);
// 輸出Profile關聯模型的email屬性
echo $user->profile->email;
;自定義關聯外鍵
namespace app\index\model;
use think\Model;
class User extends Model {
public function profile()
{
return $this->hasOne('Profile','uid');
}
}
;關聯查詢
// 查詢有檔案記錄的用戶
$user = User::has('profile')->find();
// 查詢年齡是20歲的用戶
$user = User::hasWhere('profile',['age'=>'20'])->select();
;關聯新增
$user = User::find(1);
// 如果還沒有關聯數據 則進行新增
$user->profile->email = 'thinkphp';
$user->profile->save();
// 或者
$user->profile->save(['email' => 'thinkphp']);
;關聯更新
$user = User::find(1);
$user->profile->email = 'thinkphp';
$user->profile->save();
// 或者
$user->profile->save(['email' => 'thinkphp']);
~~~
~~~
;相對關聯定義
class Profile extends Model {
public function user()
{
return $this->belongsTo('User');
}
}
相對關聯查詢
$profile = Profile::find(1);
// 輸出User關聯模型的屬性
echo $profile->user->account;
~~~
~~~
;一對多關聯定義
class Article extends Model {
public function comments()
{
return $this->hasMany('Comment');
}
}
;一對多自定義主鍵
class Article extends Model {
public function comments()
{
return $this->hasMany('Comment','art_id');
}
}
;關聯查詢
$article = Article::find(1);
// 獲取文章的所有評論
dump($article->comments);
// 也可以進行條件搜索
dump($article->comments()->where('status',1)->select());
// 查詢評論超過3個的文章
$list = Article::has('comments','>',3)->select();
// 查詢評論狀態正常的文章
$list = Article::hasWhere('comments',['status'=>1])->select();
;關聯新增
$article = Article::find(1);
// 增加一個關聯數據
$article->comments()->save(['content'=>'test']);
// 批量增加關聯數據
$article->comments()->saveAll([
['content'=>'thinkphp'],
['content'=>'onethink'],
]);
~~~
~~~
;多對多關聯
class User extends Model {
public function roles()
{
return $this->belongsToMany('Role');
}
}
;關聯查詢
$user = User::get(1);
// 獲取用戶的所有角色
dump($user->roles);
// 也可以進行條件搜索
dump($user->roles()->where('name','admin')->select());
;關聯新增
$user = User::get(1);
// 增加關聯數據 會自動寫入中間表數據
$user->roles()->save(['name'=>'管理員']);
// 批量增加關聯數據
$user->roles()->saveAll([
['name'=>'管理員'],
['name'=>'操作員'],
]);
;單獨新增中間表
$user = User::get(1);
// 僅增加關聯的中間表數據
$user->roles()->save(1);
// 或者
$role = Role::get(1);
$user->roles()->save($role);
// 批量增加關聯數據
$user->roles()->saveAll([1,2,3]);
;單獨更新中間表
$user = User::get(1);
// 增加關聯的中間表數據
$user->roles()->attach(1);
// 傳入中間表的額外屬性
$user->roles()->attach(1,['remark'=>'test']);
// 刪除中間表數據
$user->roles()->detach([1,2,3]);
~~~
#### 27 db() 初始化模型的數據庫對象
~~~
public static function db()
~~~
#### 28 __call() __callStatic() __set() __get() __isset() __unset() __toString() __wakeup()攔截方法
~~~
;實例對象調用支持
public function __call($method, $args)
;類靜態調用支持
public static function __callStatic($method, $params)
;修改數據$this->data
public function __set($name, $value)
;獲取數據$this->data
public function __get($name)
;檢查數據是否存在
public function __isset($name)
;刪除數據
public function __unset($name)
;字符串輸出
public function __toString()
;解序列化后處理
public function __wakeup()
~~~
#### 29 jsonSerialize() 序列化接口實現
~~~
public function jsonSerialize()
~~~
> json序列化輸出數據$data
~~~
echo json_encode(User::find(1));
{"id":"1","name":"","title":"","status":"1","update_time":"1430409600","score":"90.5"}
~~~
#### 30 offsetSet() offsetExists() offsetUnset() offsetGet()數組訪問支持
~~~
public function offsetSet($name, $value)
public function offsetExists($name)
public function offsetUnset($name)
public function offsetGet($name)
~~~
~~~
$user = User::find(1);
echo $user->name ; // 有效
echo $user['name'] // 同樣有效
$user->name = 'thinkphp'; // 有效
$user['name'] = 'thinkphp'; // 同樣有效
$user->save();
~~~
### 2-4protected成員方法
~~~
protected function initialize() ;模型初始化接口
protected static function init() ;模型初始化回調
protected function isPk($key) ;判斷$key是否為主鍵
protected function autoCompleteData($auto = []) ;處理字段更新字段列表
protected function trigger($event, &$params) ;觸發注冊的事件回調
protected static function parseQuery(&$data, $with, $cache) ;分析查詢表達式
protected function parseModel($model) ;解析模型的命名空間
~~~
## 3 新模型總結
- 更新記錄
- 概述
- 文件索引
- 函數索引
- 章節格式
- 框架流程
- 前:章節說明
- 主:(index.php)入口
- 主:(start.php)框架引導
- 主:(App.php)應用啟動
- 主:(App.php)應用調度
- C:(Controller.php)應用控制器
- M:(Model.php)數據模型
- V:(View.php)視圖對象
- 附:(App.php)應用啟動
- 附:(base.php)全局變量
- 附:(common.php)模式配置
- 附:(convention.php)全局配置
- 附:(Loader.php)自動加載器
- 附:(Build.php)自動生成
- 附:(Hook.php)監聽回調
- 附:(Route.php)全局路由
- 附:(Response.php)數據輸出
- 附:(Log.php)日志記錄
- 附:(Exception.php)異常處理
- 框架工具
- 另:(helper.php)輔助函數
- 另:(Cache.php)數據緩存
- 另:(Cookie.php)cookie操作
- 另:(Console.php)控制臺
- 另:(Debug.php)開發調試
- 另:(Error.php)錯誤處理
- 另:(Url.php)Url操作文件
- 另:(Loader.php)加載器實例化
- 另:(Input.php)數據輸入
- 另:(Lang.php)語言包管理
- 另:(ORM.php)ORM基類
- 另:(Process.php)進程管理
- 另:(Session.php)session操作
- 另:(Template.php)模板解析
- 框架驅動
- D:(\config)配置解析
- D:(\controller)控制器擴展
- D:(\model)模型擴展
- D:(\db)數據庫驅動
- D:(\view)模板解析
- D:(\template)模板標簽庫
- D:(\session)session驅動
- D:(\cache)緩存驅動
- D:(\console)控制臺
- D:(\process)進程擴展
- T:(\traits)Trait目錄
- D:(\exception)異常實現
- D:(\log)日志驅動
- 使用范例
- 服務器與框架的安裝
- 控制器操作
- 數據模型操作
- 視圖渲染控制
- MVC開發初探
- 模塊開發
- 入口文件定義全局變量
- 運行模式開發
- 框架配置
- 自動生成應用
- 事件與插件注冊
- 路由規則注冊
- 輸出控制
- 多種應用組織
- 綜合應用
- tp框架整合后臺auto架構快速開發
- 基礎原理
- php默認全局變量
- php的魔術方法
- php命名空間
- php的自動加載
- php的composer
- php的反射
- php的trait機制
- php設計模式
- php的系統時區
- php的異常錯誤
- php的輸出控制
- php的正則表達式
- php的閉包函數
- php的會話控制
- php的接口
- php的PDO
- php的字符串操作
- php的curl
- 框架心得
- 心:整體結構
- 心:配置詳解
- 心:加載器詳解
- 心:輸入輸出詳解
- 心:url路由詳解
- 心:模板詳解
- 心:模型詳解
- 心:日志詳解
- 心:緩存詳解
- 心:控制臺詳解
- 框架更新
- 4.20(驗證類,助手函數)
- 4.27(新模型Model功能)
- 5.4(新數據庫驅動)
- 7.28(自動加載)