[TOC]
* * * * *
## 1 模型基类文件分析(thinkphp/library/think/Model.php)
>[info] 成员变量
~~~
操作状态标记:1新增2更新3全部
const MODEL_INSERT = 1;
const MODEL_UPDATE = 2;
const MODEL_BOTH = 3;
验证装有标记:1存在验证2必须验证3有值验证
const EXISTS_VALIDATE = 0;
const MUST_VALIDATE = 1;
const VALUE_VALIDATE = 2;
数据库操作对象,对象池,主键,表前缀
protected $db = null;
private $links = [];
protected $pk = null;
protected $tablePrefix = null;
模型名称,数据库名称,数据库配置,
protected $name = '';
protected $dbName = '';
protected $connection = [];
无前缀数据表名,带前缀实际数据表名
protected $tableName = '';
protected $trueTableName = '';
错误信息,字段信息,数据信息,数据副本
protected $error = '';
protected $fields = [];
protected $data = [];
protected $duplicate = [];
查询表达式,命名范围,字段映射,字段验证
protected $options = [];
protected $scope = [];
protected $map = [];
protected $rule = [];
~~~
>[info] 58个public方法
* * * * *
> 构造函数
`public function __construct($name = '', array $config = [])`
> __set() __get() __isset() __unset() 数据对象$data的值
`public function __set($name, $value)`
`public function __get($name)`
`public function __isset($name)`
`public function __unset($name)`
> __call()调用内置方法
`public function __call($method, $args)`
> add() addAll() 添加数据
`public function add($data = '', $replace = false)`
`public function addAll($dataList, $options = [], $replace = false)`
> save() 更新数据
`public function save($data = '')`
> delete()删除数据
`public function delete($options = [])`
> select() 查询多条数据
`public function select($options = [])`
> getField()获取字段的值
`public function getField($field, $sepa = null)`
> setFiled() 设置字段的值
`public function setField($field, $value = '')`
> setInc() 自增更新
`public function setInc($field, $step = 1, $lazyTime = 0)`
> setDec() 自减更新
`public function setDec($field, $step = 1, $lazyTime = 0)`
> buildSql() 生成查询sql
`public function buildSql()`
> find() 获取单行数据
`public function find($options = [])`
> create() 使用post数据创建数据对象,并经过自动验证,自动填充,数据过滤。
`public function create($data = '')`
> data() 创建数据对象,没有自动验证,自动填充,数据过滤等
`public function data($data = '')`
> db() 切换当前数据库
`public function db($linkId = '', $config = '')`
> getModelName() 获取模型名称
`public function getModelName()`
> getTableName() 获取表名称
`public function getTableName()`
> getError() 返回模型的错误信息
`public function getError()`
> getDbError 返回数据库的错误信息
`public function getDbError()`
> getlastInsID() 返回最后插入的ID
`public function getLastInsID()`
> getLastSql() 返回最后执行的Sql语句
`public function getLastSql()`
> getPk() 获取数据表主键名称
`public function getPk($tableName = '')`
> getFields() 获取数据表字段信息
`public function getFields($tableName = '')`
> getTableInfo() 获取数据表信息
`public function getTableInfo($fetch = '', $tableName = '')`
> query() sql查询
`public function query($sql, $bind = [])`
> execute() sql执行
`public function execute($sql, $bind = [])`
> _join() sql组装
`public function _join($join, $type = 'INNER')`
> join() 组装join的sql
`public function join($join, $condition = null, $type = 'INNER')`
> union() 组装union的sql
`public function union($union, $all = false)`
> cache() 数据查询缓存
`public function cache($key = true, $expire = null, $type = '')`
> field() 指定查询字段
`public function field($field, $except = false)`
> scope() 调用命名范围
`public function scope($scope = '', $args = null)`
> where() 生成where语句
`public function where($where)`
> limit() 生成limit语句
`public function limit($offset, $length = null)`
> page() 生成page语句
`public function page($page, $listRows = null)`
> table() 指定数据表
`public function table($table)`
> using() USING支持,多表删除
`public function using($using)`
> order() 生成order语句
`public function order($field, $order = null)`
> group() 生成group语句
`public function group($group)`
> having() 生成having语句
`public function having($having)`
> lock() 查询锁定
`public function lock($lock = false)`
> distinct() 查询唯一
`public function distinct($distinct)`
> alias() 数据表别名
`public function alias($alias)`
> filter() 写入过滤方法
`public function filter($filter)`
> index()生成索引
`public function index($index)`
> force() 指定强制索引
`public function force($force)`
> bind() 参数绑定
`public function bind($key, $value = false)`
> comment() 生成注释
`public function comment($comment)`
> fetchSql() 生成并返回sql语句,
`public function fetchSql($fetch = true)`
> map() 设置字段映射
`public function map($map, $name = '')`
> validate() 设置字段验证
`public function validate($field = true, $rule = null)`
> auto() 设置字段自动完成
`public function auto($field = true, $rule = null)`
> master() 设置从主服务器读取数据
`public function master()`
>[info] 27个protected方法
* * * * *
> _initialize() 初始化模型回调方法
`protected function _initialize()`
> _write_data() 数据写入前回调处理数据,主要进行数据副本对比,字段映射修改,数据自动验证,数据自动填充,检查非数据字段,安全过滤,并调用_before_write()回调方法
`protected function _write_data($data, $type)`
> _before_write() 数据写入前回调处理数据
`protected function _before_write(&$data)`
> _before_insert() 数据写入前 回调处理内容
`protected function _before_insert(&$data, $options = [])`
> _after_insert() 数据写入后回调处理
`protected function _after_insert($data, $options = [])`
> _before_update() 数据更新前回调处理
`protected function _before_update(&$data, $options = [])`
> _after_update() 数据更新后回调处理
`protected function _after_update($data, $options = [])`
> _after_delete() 数据删除后回调处理
`protected function _after_delete($data, $options = [])`
> _after_select() 数据查询后回调处理
`protected function _after_select(&$resultSet, $options = [])`
> _after_find() 数据查询后回调处理
`protected function _after_find(&$result, $options = [])`
>_read_data_list() 查询返回数据的回调处理
`protected function _read_data_list($resultSet, $options)`
> _read_data() 查询返回数据的回调处理
`protected function _read_data($data, $options = [])`
>_create_filter() 创建post数据对象后的过滤方法
`protected function _create_filter(&$data)`
> _after_db() 数据切换后回调方法
`protected function _after_db()`
> parseSql() 解析sql语句
`protected function parseSql($sql)`
> parseSqlTable() 解析sql语句中的数据表名
`protected function parseSqlTable($sql)`
> parsePKWhere() 主键查询条件解析
`protected function parsePkWhere(&$options)`
> lazyWrite() 延迟更新检查
`protected function lazyWrite($guid, $step, $lazyTime)`
> dataValidate()数据验证
`protected function dataValidate(&$data)`
> dataFill() 数据自动填充
`protected function dataFill(&$data)`
> getDatabValue() 从$data获取$key对应值
`protected function getDataValue($data, $key)`
> getDataRule() 获取数据自动验证规则
`protected function getDataRule($rules, $type)`
> autoOperation() 数据自动填充处理
`protected function autoOperation($key, $val, &$data, $options = [])`
> checkValidate() 验证字段规则
`protected function checkValidate($value, $val, &$data)`
> _parseOptoons() 分析表达式
`protected function _parseOptions($options = [])`
> _parseType() 数据类型检查和自动转换
`protected function _parseType(&$data, $key, &$bind, $tableName = '')`
## 2 数据模型文件
>[info] 数据模型涉及的文件及其意义
thinkphp/library/think/Model.php 基础模型文件
thinkphp/library/think/Db.php 数据库抽象层文件
thinkphp/library/think/model/ 基础模型的扩展模型目录
thinkphp/library/think/model/Adv.php 高级模型文件
thinkphp/library/think/model/MongoModel.php MongoModel模型文件
thinkphp/library/think/model/Relation.php Realation模型文件
thinkphp/library/think/model/View.php View模型文件
thinkphp/library/think/db/ 数据库适配驱动目录
thinkphp/library/think/db/Driver.php PDO封装驱动文件
thinkphp/library/think/db/driver/Mongo.php Mongo数据库适配驱动文件
thinkphp/library/think/db/driver/Mysql.php Mysql数据库适配驱动文件
thinkphp/library/think/db/driver/Oracle.php Oracle数据库适配驱动文件
thinkphp/library/think/db/driver/Pgsql.php Pgsql数据库适配驱动文件
thinkphp/library/think/db/driver/Sqlite.php Sqlite数据库适配驱动文件
thinkphp/library/think/db/driver/Sqlsrv.php Sqlsrv数据库适配驱动文件
>[info] 数据库的配置
在全局配置文件与应用配置文件都可以定义。
应用配置文件会覆盖全局配置文件。
还可以在应用的不同模块中定义各自的数据库配置。
thinkphp/convention.php 数据库全局默认配置
~~~
'db_fields_strict' => true,
'database' => [
// 数据库类型
'type' => 'mysql',
// 数据库连接DSN配置
'dsn' => '',
// 服务器地址
'hostname' => 'localhost',
// 数据库名
'database' => '',
// 数据库用户名
'username' => 'root',
// 数据库密码
'password' => '',
// 数据库连接端口
'hostport' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => '',
// 数据库调试模式
'debug' => false,
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
],
~~~
application/database.php 数据库应用配置
~~~
return [
// 数据库类型
'type' => 'mysql',
// 数据库连接DSN配置
'dsn' => '',
// 服务器地址
'hostname' => '127.0.0.1',
// 数据库名
'database' => '',
// 数据库用户名
'username' => 'root',
// 数据库密码
'password' => '',
// 数据库连接端口
'hostport' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => '',
// 数据库调试模式
'debug' => APP_DEBUG,
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
];
~~~
## 2 文件分析
>[info] 1 根据配置文件可知,**框架默认使用mysql数据库**
>[info] 2 Model.php的构造方法__construct()中**创建连接数据库的对象**
~~~
public function __construct($name = '', array $config = [])
{
$this->_initialize();
if (!empty($name)) {
$this->name = $name;
} elseif (empty($this->name)) {
$this->name = $this->getModelName();
}
if (strpos($this->name, '.')) {
list($this->dbName, $this->name) = explode('.', $this->name);
}
if (!empty($config['prefix'])) {
$this->tablePrefix = $config['prefix'];
} elseif (isset($config['prefix']) && '' === $config['prefix']) {
$this->tablePrefix = '';
} elseif (is_null($this->tablePrefix)) {
$this->tablePrefix = Config::get('database.prefix');
}
if (!empty($config['connection'])) {
$this->connection = $config['connection'];
}
if (!empty($config['table_name'])) {
$this->tableName = $config['table_name'];
}
if (!empty($config['true_table_name'])) {
$this->trueTableName = $config['true_table_name'];
}
if (!empty($config['db_name'])) {
$this->dbName = $config['db_name'];
}
$this->db(0, $this->connection);
}
~~~
> $name:创建的模型名称,通常对应数据表名,也可以对应模型文件名称
> $config:数据库连接配置选项
` $this->_initialize();`
自定义模型初始化回调内容。可以在这里添加创建模型时调用的内容
~~~
if (!empty($name)) {
$this->name = $name;
} elseif (empty($this->name)) {
$this->name = $this->getModelName();
}
if (strpos($this->name, '.')) {
list($this->dbName, $this->name) = explode('.', $this->name);
}
~~~
获取待创建模型名称。
~~~
if (!empty($config['prefix'])) {
$this->tablePrefix = $config['prefix'];
} elseif (isset($config['prefix']) && '' === $config['prefix']) {
$this->tablePrefix = '';
} elseif (is_null($this->tablePrefix)) {
$this->tablePrefix = Config::get('database.prefix');
}
~~~
获取表前缀配置
~~~
if (!empty($config['connection'])) {
$this->connection = $config['connection'];
}
if (!empty($config['table_name'])) {
$this->tableName = $config['table_name'];
}
if (!empty($config['true_table_name'])) {
$this->trueTableName = $config['true_table_name'];
}
if (!empty($config['db_name'])) {
$this->dbName = $config['db_name'];
}
~~~
获取数据库链接选项信息
`$this->db(0, $this->connection);`
调用Model->db()方法创建数据库连接对象
>[info] 3 db()方法根据数据库链接选项信息,调用Db::connect(),创建数据库连接对象
~~~
public function db($linkId = '', $config = '')
{
if ('' === $linkId && $this->db) {
return $this->db;
}
if (!isset($this->links[$linkId])) {
if (is_string($linkId) && '' == $config) {
$config = Config::get($linkId);
}
$this->links[$linkId] = Db::connect($config);
} elseif (null === $config) {
$this->links[$linkId]->close(); // 关闭数据库连接
unset($this->links[$linkId]);
return;
}
$this->db = $this->links[$linkId];
$this->_after_db();
return $this;
}
~~~
> $linkId: 数据库连接对象缓存标识,已创建的数据库连接对象保存在Model->links变量中,减少数据库连接的创建次数。
> $config: 数据库连接配置参数信息
接上文$db->(0,$this->connection).
~~~
if ('' === $linkId && $this->db) {
return $this->db;
}
~~~
检查$this->db数据库链接对象是否存在,如果存在直接返回
~~~
if (!isset($this->links[$linkId])) {
if (is_string($linkId) && '' == $config) {
$config = Config::get($linkId);
}
$this->links[$linkId] = Db::connect($config);
}
~~~
根据$linkid检查$this->links数组是否缓存数据库链接对象
如果不存在,根据配置转换字符串形式$linkid到数据库标识id,
调用Db::connect($config)创建数据库连接对象,并保存到$this->links[$linkid]进行缓存。
`$this->db = $this->links[$linkId];`
切换模型的当前数据库连接对象
`$this->_after_db();`
数据库切换后回到方法
`return $this;`
返回$this,实现链式操作。
>[info] 4 Db.php的数据库连接对象创建,Db::connect()创建数据库连接对象
~~~
public static function connect($config = [])
{
$md5 = md5(serialize($config));
if (!isset(self::$instances[$md5])) {
$options = self::parseConfig($config);
if (empty($options['type'])) {
throw new Exception('db type error');
}
$class = (!empty($options['namespace']) ? $options['namespace'] : '\\think\\db\\driver\\') . ucwords($options['type']);
self::$instances[$md5] = new $class($options);
APP_DEBUG && Log::record('[ DB ] INIT ' . $options['type'] . ':' . var_export($options, true), 'info');
}
self::$instance = self::$instances[$md5];
return self::$instance;
}
~~~
> $config:数据库链接配置
`$md5 = md5(serialize($config));`
将数据库配置序列号并md5编码后
作为数据库连接对象实例Db::$instances数组的键名,
用来存储创建的对象实例,减少连接的创建次数,提高运行效率。
~~~
if (!isset(self::$instances[$md5])) {}
~~~
检查Db::$instances是否缓存数据库连接对象
如果没有,创建对象
~~~
$options = self::parseConfig($config);
if (empty($options['type'])) {
throw new Exception('db type error');
}
~~~
首先解析配置参数获取数据库类型$type参数,
$type决定使用哪种数据库驱动,不可缺少。
~~~
$class = (!empty($options['namespace']) ? $options['namespace'] : '\\think\\db\\driver\\') . ucwords($options['type']);
self::$instances[$md5] = new $class($options);
~~~
然后根据$type,创建thinkphp/library/think/db/driver/下对应类型的驱动对象
这里$type为mysql,因此创建mysql驱动对象。并保存到self::$instances。
`APP_DEBUG && Log::record('[ DB ] INIT ' . $options['type'] . ':' . var_export($options, true), 'info');`
记录创建连接对象日志
~~~
self::$instance = self::$instances[$md5];
return self::$instance;
~~~
保存到当前连接对象实例self::$instance,并返回
>[info] 5 mysql.php文件内容
thinkphp/library/think/db/driver/Mysql.php中
Mysql类继承PDO驱动类Dirver实现Mysql数据库的相关操作。
## 3 总结
以上是think5中数据模型涉及的文件的逻辑关系。
从数据库配置文件convention.php/database.php开始,
经基础模型Model.php的构造参数__construct()
到数据库抽象Db.php的的connect()
最后创建继承PDO的Dirver类的具体的数据库驱动Mysql对象。
然后基于数据库连接对象可以实现数据的增删改查等功能。
think5在thinkphp/helper.php文件中封装的M() D()等方法可以简化数据模型的创建
数据模型的增删改查操作见使用范例的 [数据模型操作](http://www.kancloud.cn/zmwtp/tp5/120196)
- 更新记录
- 概述
- 文件索引
- 函数索引
- 章节格式
- 框架流程
- 前:章节说明
- 主:(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(自动加载)