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

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

在上目錄中咔咔使用了query作為案例演示,這個使用在框架中是不建議使用的,因為在維護的方面會有一定的難度。

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

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

使用案例代碼

在上圖中可以看到使用了平時最常用的查詢方式,接下來將會對這組案例進行詳細分析。

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

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

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

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

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

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

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

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

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

按照上圖提供的代碼會對傳遞過來的表名進行三次判斷。

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

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

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

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

最后執(zhí)行流程

并且最后會將thinkdbQuery Object這個對象進行返回。

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

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

返回Query對象

where方法解析

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

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

指定AND查詢條件

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

這個方法平時都是跟call_user_func_array同時使用,之前咔咔也使用這倆個方法進行過一次案例實驗。

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

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

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

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

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

緊接著會進行分析查詢表達式,也就是方法parseWhereExp做的事情。

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

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

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

分析查詢表達式

在代碼的第一行就需要我們來學(xué)習(xí)的一個知識點instanceof。

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

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

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

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

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

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

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

然后在進行判斷$field instanceof Where傳遞過來的參數(shù)是否為Where類的實例。

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

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

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

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

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

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

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

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

數(shù)組批量查詢

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

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

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

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

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

where最中返回的值

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

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

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

find()執(zhí)行流程

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

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

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

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

查找單條記錄

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

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

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

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

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

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

查找單條記錄

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

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

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

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

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

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

返回結(jié)果

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