0

0

ThinkPHP之Db类库结合连接器、查询器、sql生成器使用

咔咔

咔咔

发布时间:2021-01-11 12:15:31

|

2354人浏览过

|

来源于php中文网

原创

一、Db类库巧妙结合连接器、查询器、sql生成器使用

在上目录中咔咔使用了query作为案例演示,这个使用在框架中是不建议使用的,因为在维护的方面会有一定的难度。

本节案例将会使用框架常用的查询数据库方式进行查询。

image.png

使用案例代码

在上图中可以看到使用了平时最常用的查询方式,接下来将会对这组案例进行详细分析。

同样代码会来到Db类的__callStatic这个方法,这个方法就是在调用没有声明的静态方法会进行执行的。

这个方法跟__call方法是有区别的,__call方法是调用不存在的方法会进行调用,一定要注意俩者的区别。

image.png

调用未声明的静态方法会调用

对于上图方法中static::connect()执行最后会返回 object(think\db\Query)这个对象,至于内部流程的执行可以参考第二目录的内容。

所以执行流程会来到thinkphp/library/think/db/Query.php这个类的table方法。

参数就是table中传递的数据库表名tp_test

image.png

指定当前操作的数据表

按照上图提供的代码会对传递过来的表名进行三次判断。

  • 第一次判断是否为字符串
  • 第二次判断是否存在 )
  • 第三次判断是否存在 ,

根据传递过来的字符串以上三个判断均不成立,于是会执行到下面流程。

在table这个方法中可以看到最后的执行流程就是将传递过来的表名存放在属性options这个里边。

image.png

最后执行流程

并且最后会将think\db\Query Object这个对象进行返回。

image.png

立即学习PHP免费学习笔记(深入)”;

返回Query对象

where方法解析

table方法分析完成后会紧接着执行where方法,同样还是在类thinkphp/library/think/db/Query.php

image.png

指定AND查询条件

上图中在这个类中可以看到一个方法func_get_args,这个方法会返回一个包含函数参数列表的数组。

这个方法平时都是跟call_user_func_array同时使用,之前咔咔也使用这俩个方法进行过一次案例实验。

然后会使用函数array_shift删除数组中的第一个元素(red),并返回被删除元素的值。

下图第一个结果为func_get_args这个方法获取出来的数据,第二组结果为array_shift这个方法返回的结果。

俩组结果返回的值可以进行对比一下,可以更好的理解array_shift的使用场景。

image.png

前后俩次返回结果对比

紧接着会进行分析查询表达式,也就是方法parseWhereExp做的事情。

在这个方法中需要注意一个点就是关于传递过来的这俩个参数。

参数一为查询逻辑,参数二就是在使用案例时传入的参数。

image.png

分析查询表达式

在代码的第一行就需要我们来学习的一个知识点instanceof

instanceof可以判断某个对象是否是某个类的实例,判断一个对象是否实现了某个接口。

关于这个的使用案例在文章ThinkPHP源码解析之控制器这一文中做了详细的说明。

根据学习instanceof的作用可以清晰的明白第一个判断不会进行执行。

在继续学习以下的执行流程,根据咔咔圈出来的框来进行对代码进行简单的解析。

image.png

继续学习下半部分

根据上图首先会对查询逻辑的符号全部转为小写

然后在进行判断$field instanceof Where传递过来的参数是否为Where类的实例。

最后一个判断就是$field instanceof Expression跟上一步是判断同样的功能。

所以说代码最终的执行逻辑就是下图圈到的部分。

image.png

解析数组批量查询

还记得在案例过程中给where传递的参数就是一个数组。

如果将参数改为where('t_id',1)则就会走is_string($field)的这个流程,这个流程就交给大家了,咔咔就不去解析。

这里咔咔还是使用数组作为参数进行解析,那么代码依然会执行本类的parseArrayWhereItems这个方法

image.png

数组批量查询

在这个方法中先需要知道key会返回什么,从当前内部指针位置返回元素键名。

所以代码会去执行if语句的判断,根据上边的所有判断都不符合所以会执行这段代码$where[] = [$key, is_array($val) ? 'IN' : '=', $val];

这段代码会判断循环数组的value值是否为数组,如果为数组就是in,反之为=,由于value为1所以数组的第二个值为=。

那么最终where的值就是下图打印的数据。

image.png

where最中返回的值

由于where不为空,代码执行流程会执行到下图位置,最终在返回本类实例。

image.png

将查询参数存储到option属性中

find()执行流程

接着代码会还是执行本类的find方法,查找单条记录。

由于find中是没有传递参数的,所以代码会执行到$this->parseOptions();分析表达式(可用于查询或者写入操作)

就目前写的案例而言,这段看似很长的代码大家好好看看都可以看明白,最终依然是返回当前的所有参数。

image.png

查找单条记录

以下就是返回的所以结果

image.png

AIBox 一站式AI创作平台
AIBox 一站式AI创作平台

AIBox365一站式AI创作平台,支持ChatGPT、GPT4、Claue3、Gemini、Midjourney等国内外大模型

下载
返回所有的参数结果

真正的查询数据是这块代码$result = $this->connection->find($this);,这段代码会执行到文件thinkphp/library/think/db/Connection.php

从这块代码可以看到当查询一条数据时框架默认给加上了limit为1,至于为什么这么加你就需要查看一下sql优化方面的知识了。

image.png

查找单条记录

在这里就是关于sql语句的生成,代码自己好好看看就会明白,咔咔解析的只是执行流程和具体代码简单的了解一下即可。

至于具体实现流程咔咔在后期如果有机会会单独把每个方法进行深度解析,那时就是主要针对代码的解析。

image.png

根据一定的规则生成sql语句,并且进行查询

最终返回结果如下

image.png

返回结果

以上就是关于Db在结合连接器,查询器,生成器实现的数据库查询功能。

截止到这里关于Db的场景就分析到这里,接下来咔咔将会对Model进行简单的分析。

二、关于getLastSql的实现过程

还是之前的案例,我们来使用这个方法打印一下结果来看一下是什么。

image.png

打印案例

看到上图就知道是框架最终给生成的SQL语句,那么接下来咔咔就会带大家一起来探讨一下,这个sql语句是如何生成的。

下图为本次演示的案例,也就是咔咔下图圈出来的地方。

image.png

演示案例

从上图圈出来的地方进行代码追踪会到文件thinkphp/library/think/Db.php,并且会去执行本类的__callStatic方法,这个方法就不在进行解释了,在上文和之前也已经提到过多次了。

并且返回结果也不去做声明了,上文也提到了,这里只需要知道最终返回结果为返回 object(think\db\Query)

image.png

调用未声明的静态方法时会进行执行

根据上图的返回结果可以知道最终回去调用object(think\db\Query)这个类的getLastSql这个方法

根据这个方法可以知道是获取最近一次查询的sql语句。

image.png

获取最近一次查询的sql语句

这里就会有点疑问了,关于属性connection到底是什么,这里在进行一次简单的简析。

关于这种属性的声明一般都会在本类的构造函数或者父类的构造函数中进行声明,这也是在阅读源码时的一个小窍门。

于是我们首先就需要来到本类的构造函数来看一眼。

image.png

架构函数

通过上图可以得知,此处使用了依赖注入的方式,所以Connection就是一个对象,并且也是框架中所谓的连接器。

所以说这个Connection对象就是下图打印出来的。

image.png

连接器的对象打印结果

根据上图得知使用的类文件应该就是think\db\connector\Mysql那么就会执行这个类里边的getLastSql方法。

但是来到这个类执行你会发现这个类里边根本是没有这个方法。

image.png

继承关系

根据上图的继承关系,我们就知道这个方法是在thinkphp/library/think/db/Connection.php这个类文件里边。

下图即是这个方法执行过程,可以看到存在俩个参数,但是这俩个参数还是一头雾水根本不知道是什么。

image.png

获取最近一次查询的sql语句

根据代码追踪我们对上图所出现的俩个参数先进行简单的说明

  • $this->queryStr当前SQL指令
  • $this->bind 绑定参数

追踪$this->queryStr这个属性值

走到这里估计有点蒙了吧!对于这个值有点确定不了了,指定不是靠打印可以获取到结果的。

当然还有另一种办法就是进行debug来断点调试。

但是既然咔咔带大家看源码呢!就不会用上边的俩种方式,会直接从源码中找到蛛丝马迹。

根据咔咔上边给提供的案例,执行的最后一步就是find方法,这个方法也是在thinkphp/library/think/db/Connection.php这个类里边,寻找单条记录。

那么我们就在这个方法中进行一点点的寻找,这里咔咔已经给大家圈好了,就是下图咔咔圈其起来的地方。

image.png

执行查询

根据上图咔咔给的代码注释,第一个参数就是生成的SQL语句,来继续追踪这个方法看一下,此时这个方法依然会在本类thinkphp/library/think/db/Connection.php这个文件中实现query方法。

在这个方法中一眼就可以看见对于这个queryStr属性的设置,是直接给这个属性赋值,那么也就是说这个属性的值就是上一个SQL语句生成的SQL语句。

image.png

执行查询 返回数据集

所以说这个getLastSql获取的就是在这个语句之前执行的SQL语句,也只能获取出最近执行的那个SQL语句。

以上就是关于getLastSql的实现原理,在这里需要注意的就是关于SQL的生成,这块属实有点复杂。

总结

截止到这里关于数据库中Db类的操作场景分析以及关于结合连接器,查询器,生成器就到这里结束了。

这里咔咔主要就是使用了俩种案例来进行执行,第一种为原生案例,第二种为框架封装的案例。

使用了这俩种案例来对源码进行了深度解析,但是在文档还有很多的实现方法,其它的方法只需要根据咔咔给的提示然后一点点解析即可。

不需要对所有的方法都进行执行,不管任何方法走的都是上文分析的方法,也是很简单。

最后在演示了一下关于使用getLastSql来获取最后一次执行的SQL语句查询,这里的实现原理主要就是在Db类操作数据库时,不管是使用find方法还是select方法最终都会走向一个方法那就是query方法。

同样在这个方法中存在一个属性值queryStr,也就是在这个时候将SQL语句赋值进去的,然后在使用getLastSql这个方法使用queryStr和bind属性在对SQL进行拼接,最总返回SQL语句。

坚持学习、坚持写博、坚持分享是咔咔从业以来一直所秉持的信念。希望在偌大互联网中咔咔的文章能带给你一丝丝帮助。我是咔咔,下期见。

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

46

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

178

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

51

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

92

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

102

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

227

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

532

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

171

2026.03.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号