[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(自动加载)