ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

一、Db類庫(kù)巧妙結(jié)合連接器、查詢器、sql生成器使用

在上目錄中咔咔使用了query作為案例演示,這個(gè)使用在框架中是不建議使用的,因?yàn)樵诰S護(hù)的方面會(huì)有一定的難度。

本節(jié)案例將會(huì)使用框架常用的查詢數(shù)據(jù)庫(kù)方式進(jìn)行查詢。

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

使用案例代碼

在上圖中可以看到使用了平時(shí)最常用的查詢方式,接下來(lái)將會(huì)對(duì)這組案例進(jìn)行詳細(xì)分析。

同樣代碼會(huì)來(lái)到Db類的__callStatic這個(gè)方法,這個(gè)方法就是在調(diào)用沒有聲明的靜態(tài)方法會(huì)進(jìn)行執(zhí)行的。

這個(gè)方法跟__call方法是有區(qū)別的,__call方法是調(diào)用不存在的方法會(huì)進(jìn)行調(diào)用,一定要注意倆者的區(qū)別。

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

調(diào)用未聲明的靜態(tài)方法會(huì)調(diào)用

對(duì)于上圖方法中static::connect()執(zhí)行最后會(huì)返回?object(thinkdbQuery)這個(gè)對(duì)象,至于內(nèi)部流程的執(zhí)行可以參考第二目錄的內(nèi)容。

所以執(zhí)行流程會(huì)來(lái)到thinkphp/library/think/db/Query.php這個(gè)類的table方法。

參數(shù)就是table中傳遞的數(shù)據(jù)庫(kù)表名tp_test。

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

指定當(dāng)前操作的數(shù)據(jù)表

按照上圖提供的代碼會(huì)對(duì)傳遞過(guò)來(lái)的表名進(jìn)行三次判斷。

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

根據(jù)傳遞過(guò)來(lái)的字符串以上三個(gè)判斷均不成立,于是會(huì)執(zhí)行到下面流程。

在table這個(gè)方法中可以看到最后的執(zhí)行流程就是將傳遞過(guò)來(lái)的表名存放在屬性options這個(gè)里邊。

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

最后執(zhí)行流程

并且最后會(huì)將thinkdbQuery Object這個(gè)對(duì)象進(jìn)行返回。

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

立即學(xué)習(xí)PHP免費(fèi)學(xué)習(xí)筆記(深入)”;

返回Query對(duì)象

where方法解析

table方法分析完成后會(huì)緊接著執(zhí)行where方法,同樣還是在類thinkphp/library/think/db/Query.php

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

指定AND查詢條件

上圖中在這個(gè)類中可以看到一個(gè)方法func_get_args,這個(gè)方法會(huì)返回一個(gè)包含函數(shù)參數(shù)列表的數(shù)組。

這個(gè)方法平時(shí)都是跟call_user_func_array同時(shí)使用,之前咔咔也使用這倆個(gè)方法進(jìn)行過(guò)一次案例實(shí)驗(yàn)。

然后會(huì)使用函數(shù)array_shift刪除數(shù)組中的第一個(gè)元素(red),并返回被刪除元素的值。

下圖第一個(gè)結(jié)果為func_get_args這個(gè)方法獲取出來(lái)的數(shù)據(jù),第二組結(jié)果為array_shift這個(gè)方法返回的結(jié)果。

倆組結(jié)果返回的值可以進(jìn)行對(duì)比一下,可以更好的理解array_shift的使用場(chǎng)景。

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

前后倆次返回結(jié)果對(duì)比

緊接著會(huì)進(jìn)行分析查詢表達(dá)式,也就是方法parseWhereExp做的事情。

在這個(gè)方法中需要注意一個(gè)點(diǎn)就是關(guān)于傳遞過(guò)來(lái)的這倆個(gè)參數(shù)。

參數(shù)一為查詢邏輯,參數(shù)二就是在使用案例時(shí)傳入的參數(shù)。

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

分析查詢表達(dá)式

在代碼的第一行就需要我們來(lái)學(xué)習(xí)的一個(gè)知識(shí)點(diǎn)instanceof。

instanceof可以判斷某個(gè)對(duì)象是否是某個(gè)類的實(shí)例,判斷一個(gè)對(duì)象是否實(shí)現(xiàn)了某個(gè)接口。

關(guān)于這個(gè)的使用案例在文章ThinkPHP源碼解析之控制器這一文中做了詳細(xì)的說(shuō)明。

根據(jù)學(xué)習(xí)instanceof的作用可以清晰的明白第一個(gè)判斷不會(huì)進(jìn)行執(zhí)行。

在繼續(xù)學(xué)習(xí)以下的執(zhí)行流程,根據(jù)咔咔圈出來(lái)的框來(lái)進(jìn)行對(duì)代碼進(jìn)行簡(jiǎn)單的解析。

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

繼續(xù)學(xué)習(xí)下半部分

根據(jù)上圖首先會(huì)對(duì)查詢邏輯的符號(hào)全部轉(zhuǎn)為小寫

然后在進(jìn)行判斷$field instanceof Where傳遞過(guò)來(lái)的參數(shù)是否為Where類的實(shí)例。

最后一個(gè)判斷就是$field instanceof Expression跟上一步是判斷同樣的功能。

所以說(shuō)代碼最終的執(zhí)行邏輯就是下圖圈到的部分。

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

解析數(shù)組批量查詢

還記得在案例過(guò)程中給where傳遞的參數(shù)就是一個(gè)數(shù)組。

如果將參數(shù)改為where(‘t_id’,1)則就會(huì)走is_string($field)的這個(gè)流程,這個(gè)流程就交給大家了,咔咔就不去解析。

這里咔咔還是使用數(shù)組作為參數(shù)進(jìn)行解析,那么代碼依然會(huì)執(zhí)行本類的parseArrayWhereItems這個(gè)方法

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

數(shù)組批量查詢

在這個(gè)方法中先需要知道key會(huì)返回什么,從當(dāng)前內(nèi)部指針位置返回元素鍵名。

所以代碼會(huì)去執(zhí)行if語(yǔ)句的判斷,根據(jù)上邊的所有判斷都不符合所以會(huì)執(zhí)行這段代碼$where[] = [$key, is_array($val) ? ‘IN’ : ‘=’, $val];

這段代碼會(huì)判斷循環(huán)數(shù)組的value值是否為數(shù)組,如果為數(shù)組就是in,反之為=,由于value為1所以數(shù)組的第二個(gè)值為=。

那么最終where的值就是下圖打印的數(shù)據(jù)。

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

where最中返回的值

由于where不為空,代碼執(zhí)行流程會(huì)執(zhí)行到下圖位置,最終在返回本類實(shí)例。

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

將查詢參數(shù)存儲(chǔ)到option屬性中

find()執(zhí)行流程

接著代碼會(huì)還是執(zhí)行本類的find方法,查找單條記錄。

由于find中是沒有傳遞參數(shù)的,所以代碼會(huì)執(zhí)行到$this->parseOptions();分析表達(dá)式(可用于查詢或者寫入操作)

就目前寫的案例而言,這段看似很長(zhǎng)的代碼大家好好看看都可以看明白,最終依然是返回當(dāng)前的所有參數(shù)。

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

查找單條記錄

以下就是返回的所以結(jié)果

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

返回所有的參數(shù)結(jié)果

真正的查詢數(shù)據(jù)是這塊代碼$result = $this->connection->find($this);,這段代碼會(huì)執(zhí)行到文件thinkphp/library/think/db/Connection.php

從這塊代碼可以看到當(dāng)查詢一條數(shù)據(jù)時(shí)框架默認(rèn)給加上了limit為1,至于為什么這么加你就需要查看一下sql優(yōu)化方面的知識(shí)了。

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

查找單條記錄

在這里就是關(guān)于sql語(yǔ)句的生成,代碼自己好好看看就會(huì)明白,咔咔解析的只是執(zhí)行流程和具體代碼簡(jiǎn)單的了解一下即可。

至于具體實(shí)現(xiàn)流程咔咔在后期如果有機(jī)會(huì)會(huì)單獨(dú)把每個(gè)方法進(jìn)行深度解析,那時(shí)就是主要針對(duì)代碼的解析。

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

根據(jù)一定的規(guī)則生成sql語(yǔ)句,并且進(jìn)行查詢

最終返回結(jié)果如下

ThinkPHP之Db類庫(kù)結(jié)合連接器、查詢器、sql生成器使用

返回結(jié)果

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊12 分享