四、关于getLastSql的实现过程
还是之前的案例,我们来使用这个方法打印一下结果来看一下是什么。
看到上图就知道是框架最终给生成的SQL语句,那么接下来咔咔就会带大家一起来探讨一下,这个sql语句是如何生成的。
下图为本次演示的案例,也就是咔咔下图圈出来的地方。
从上图圈出来的地方进行代码追踪会到文件thinkphp/library/think/Db.php,并且会去执行本类的__callStatic方法,这个方法就不在进行解释了,在上文和之前也已经提到过多次了。
并且返回结果也不去做声明了,上文也提到了,这里只需要知道最终返回结果为返回 object(think\db\Query)
根据上图的返回结果可以知道最终回去调用object(think\db\Query)这个类的getLastSql这个方法
根据这个方法可以知道是获取最近一次查询的sql语句。
这里就会有点疑问了,关于属性connection到底是什么,这里在进行一次简单的简析。
关于这种属性的声明一般都会在本类的构造函数或者父类的构造函数中进行声明,这也是在阅读源码时的一个小窍门。
于是我们首先就需要来到本类的构造函数来看一眼。
通过上图可以得知,此处使用了依赖注入的方式,所以Connection就是一个对象,并且也是框架中所谓的连接器。
所以说这个Connection对象就是下图打印出来的。
根据上图得知使用的类文件应该就是think\db\connector\Mysql那么就会执行这个类里边的getLastSql方法。
但是来到这个类执行你会发现这个类里边根本是没有这个方法。
根据上图的继承关系,我们就知道这个方法是在thinkphp/library/think/db/Connection.php这个类文件里边。
下图即是这个方法执行过程,可以看到存在俩个参数,但是这俩个参数还是一头雾水根本不知道是什么。
根据代码追踪我们对上图所出现的俩个参数先进行简单的说明
- $this->queryStr当前SQL指令
- $this->bind 绑定参数
追踪$this->queryStr这个属性值
走到这里估计有点蒙了吧!对于这个值有点确定不了了,指定不是靠打印可以获取到结果的。
当然还有另一种办法就是进行debug来断点调试。
但是既然咔咔带大家看源码呢!就不会用上边的俩种方式,会直接从源码中找到蛛丝马迹。
根据咔咔上边给提供的案例,执行的最后一步就是find方法,这个方法也是在thinkphp/library/think/db/Connection.php这个类里边,寻找单条记录。
那么我们就在这个方法中进行一点点的寻找,这里咔咔已经给大家圈好了,就是下图咔咔圈其起来的地方。
根据上图咔咔给的代码注释,第一个参数就是生成的SQL语句,来继续追踪这个方法看一下,此时这个方法依然会在本类thinkphp/library/think/db/Connection.php这个文件中实现query方法。
在这个方法中一眼就可以看见对于这个queryStr属性的设置,是直接给这个属性赋值,那么也就是说这个属性的值就是上一个SQL语句生成的SQL语句。
所以说这个getLastSql获取的就是在这个语句之前执行的SQL语句,也只能获取出最近执行的那个SQL语句。
以上就是关于getLastSql的实现原理,在这里需要注意的就是关于SQL的生成,这块属实有点复杂。
五、总结
截止到这里关于数据库中Db类的操作场景分析以及关于结合连接器,查询器,生成器就到这里结束了。
这里咔咔主要就是使用了俩种案例来进行执行,第一种为原生案例,第二种为框架封装的案例。
使用了这俩种案例来对源码进行了深度解析,但是在文档还有很多的实现方法,其它的方法只需要根据咔咔给的提示然后一点点解析即可。
不需要对所有的方法都进行执行,不管任何方法走的都是上文分析的方法,也是很简单。
最后在演示了一下关于使用getLastSql来获取最后一次执行的SQL语句查询,这里的实现原理主要就是在Db类操作数据库时,不管是使用find方法还是select方法最终都会走向一个方法那就是query方法。
同样在这个方法中存在一个属性值queryStr,也就是在这个时候将SQL语句赋值进去的,然后在使用getLastSql这个方法使用queryStr和bind属性在对SQL进行拼接,最总返回SQL语句。