在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