tp5源码解析--Db操作
- 陈大剩
- 2020-06-13 16:20:25
- 5523
在TP5的框架使用过程中,Db类是一定会接触到的,上手不难,但若想随心所欲的用,还是需要了解一番。用了千次,却没看过一次源码,学习源码,起码对TP5这个框架使用更加得心应手,毕竟技术服务于业务,能够写出更简介、更方便、更有效的业务代码,本身就是一件身心愉悦的事儿;
Db调用流程
其实就是一个简单的单例
Db类解析
//存储实例
private static $instance = [];
//查询次数
public static $queryTimes = 0;
//执行次数
public static $executeTimes = 0;
//负杂的单例,获得数据库连接实例
//单例或切换数据库连接,取决于传入的$config配置数组
public static function connect($config = [], $name = false){}
// 清除连接实例
public static function clear(){}
//数据库连接参数解析
private static function parseConfig($config){}
//DSN 解析
private static function parseDsn($dsnStr){}
//调用驱动类的方法,此方法及其重要,当用静态调用的方法,不存在时会使用此方法;
//此方法会利用connect()方法生成的单例,再去访问\think\db\connector\Mysql类里的方法;
public static function __callStatic($method, $params){}
connector\Mysql类解析
// 对应一个类名,builder创建具体的SQL语句
protected $builder = '\\think\\db\\builder\\Mysql';
//解析pdo连接的dsn信息
protected function parseDsn($config){}
//取得数据表的字段信息
public function getFields($tableName){}
//取得数据库的表信息
public function getTables($dbName = ''){}
//SQL性能分析
protected function getExplain($sql){}
//判断是否支持事务嵌套
protected function supportSavepoint(){}
Connector类解析
此类为Connector\Mysql类的父类,Connection是一个抽象类,数据库操作相关操作类,是PDO的一些配置及实例。 其中包含:
- 将本类作为单例传入,实例化Query对象,执行链式方法,如table()、where()、find();
- 创建单例Mysql连接,分布式环境下若从库连接失败会自动连接主库;
- query()执行查询,返回结果集;
- execute()执行语句,返回影响行数;
- 事务处理;
- 批量执行SQL,自动启动事务支持,需将SQl存入到数组内传入;
- 获取最近插入的ID;
- 获取最近的错误信息,封装PDOStatement的error;
- SQL执行时间记录、性能分析、事件监听;
- 获取最近执行的SQL;
// PDO连接参数
$params = [
PDO::ATTR_CASE => PDO::CASE_NATURAL, //强制列名为指定的大小写=>保留数据库驱动返回的列名。
PDO::ATTR_ERRMODE=> PDO::ERRMODE_EXCEPTION,//设置抛出异常
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,//转换 NULL 和空字符串=> 不转换
PDO::ATTR_STRINGIFY_FETCHES => false,//提取的时候将数值转换为字符串
PDO::ATTR_EMULATE_PREPARES => false,//启用或禁用预处理语句的模拟
];
//初始数据化连接
protected function initConnect($master = true){}
//析构方法 释放数据连接
public function __destruct(){}
//释放查询结果
public function free(){}
//执行语句
public function execute($sql, $bind = [], Query $query = null){}
//执行查询 返回数据集
public function query($sql, $bind = [], $master = false, $pdo = false){}
//连接数据库方法
public function connect(array $config = [], $linkNum = 0, $autoConnection = false){}
Query类和Builder浅谈
Query类为链式操作类,个人认为此类相当于中间商类。利用本身链式操作,借助getQuery($this)单例和Sql构造类制作的Sql进查询并返回结果,Mode则执行集合方法后返回;
Builder类为Sql构造类,组装通过写好的Sql语句,在通过字符串匹配形成Curd sql语句,在返回给Query类;
Builder的select模版如:
SELECT%DISTINCT% %FIELD% FROM %TABLE%%FORCE%%JOIN%%WHERE%%GROUP%%HAVING%%UNION%%ORDER%%LIMIT%%LOCK%%COMMENT%
//按照参数类型作对应替换,最后生成一条完整SQL;
详细流程如下:
关于PHPstom提示问题
Db类内部没有找到table()静态方法,可是我们在开发时,输入Db+两个引号,会弹出多个方法提示,其中包括了table()。这就觉得有点奇怪了,打开Db代码,发现包含了大堆对method的注释。我照着新增@method注解后,自定义方式IDE也会提示了!真是个好玩意儿,比如我喜欢把redis封装成单例工具类。那么再某些情况下,实例对象调用方法时,调试上不太友好。基于Db的类注释,刚刚已经确认能够在开发中增加提示,让开发过程更舒服。
/**
* Class Db
* @package think
* @method Query table(string $table) static 指定数据表(含前缀)
* @method Query name(string $name) static 指定数据表(不含前缀)
* @method Query where(mixed $field, string $op = null, mixed $condition = null) static 查询条件
* @method Query join(mixed $join, mixed $condition = null, string $type = 'INNER') static JOIN查询
* @method Query union(mixed $union, boolean $all = false) static UNION查询
* @method Query limit(mixed $offset, integer $length = null) static 查询LIMIT
* @method Query order(mixed $field, string $order = null) static 查询ORDER
* @method Query cache(mixed $key = null , integer $expire = null) static 设置查询缓存
* @method mixed value(string $field) static 获取某个字段的值
* @method array column(string $field, string $key = '') static 获取某个列的值
* @method Query view(mixed $join, mixed $field = null, mixed $on = null, string $type = 'INNER') static 视图查询
* @method mixed find(mixed $data = null) static 查询单个记录
* @method mixed select(mixed $data = null) static 查询多个记录
* @method integer insert(array $data, boolean $replace = false, boolean $getLastInsID = false, string $sequence = null) static 插入一条记录
* @method integer insertGetId(array $data, boolean $replace = false, string $sequence = null) static 插入一条记录并返回自增ID
* @method integer insertAll(array $dataSet) static 插入多条记录
* @method integer update(array $data) static 更新记录
* @method integer delete(mixed $data = null) static 删除记录
* @method boolean chunk(integer $count, callable $callback, string $column = null) static 分块获取数据
* @method mixed query(string $sql, array $bind = [], boolean $master = false, bool $pdo = false) static SQL查询
* @method integer execute(string $sql, array $bind = [], boolean $fetch = false, boolean $getLastInsID = false, string $sequence = null) static SQL执行
* @method Paginator paginate(integer $listRows = 15, mixed $simple = null, array $config = []) static 分页查询
* @method mixed transaction(callable $callback) static 执行数据库事务
* @method void startTrans() static 启动事务
* @method void commit() static 用于非自动提交状态下面的查询提交
* @method void rollback() static 事务回滚
* @method boolean batchQuery(array $sqlArray) static 批处理执行SQL语句
* @method string quote(string $str) static SQL指令安全过滤
* @method string getLastInsID($sequence = null) static 获取最近插入的ID
*/
参考:dobat