ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析

終于快來到框架解析的結(jié)尾了,本文將會(huì)帶領(lǐng)大家領(lǐng)略框架中的模型以及視圖的奧秘。

前言

在日常開發(fā)過程中模型的使用是非常之多的,但是在開發(fā)過程只知道如何使用,并不知道內(nèi)在是如何實(shí)現(xiàn)的,模型是不管接口還是后臺(tái)都會(huì)使用到的東西。

關(guān)于視圖在前后臺(tái)分離的大趨勢下,框架存在視圖大多數(shù)還是針對于后臺(tái)開發(fā)的使用。

本文也是對框架解讀快到最后階段了,接下來咔咔將帶領(lǐng)大家一起學(xué)習(xí)關(guān)于在框架中Db類的奧秘。

下圖為咔咔提供的腦圖可以根據(jù)這個(gè)腦圖進(jìn)行閱讀文章。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
數(shù)據(jù)庫執(zhí)行流程

一、Db操作類和其它類對應(yīng)關(guān)系解刨

在學(xué)習(xí)模型之前一定要知道的就是DB這個(gè)類,這個(gè)類也是對數(shù)據(jù)庫的操作。

在框架中存在這樣一個(gè)配置文件,在這個(gè)配置文件里邊會(huì)存在關(guān)于數(shù)據(jù)庫配置的一系列信息。

在接下來的過程中咔咔也會(huì)簡單的創(chuàng)建一個(gè)數(shù)據(jù)庫來做演示。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
數(shù)據(jù)庫配置文件

同樣在框架的核心層存在倆個(gè)類,分別為Db類和Model類,這倆個(gè)類就是接下來的解析對象。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
框架核心層需要知道的倆個(gè)類

在解析Db操作類和其它類對應(yīng)關(guān)系解刨之前,我們先創(chuàng)建一個(gè)數(shù)據(jù)庫作為演示使用。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
演示數(shù)據(jù)庫

首先先來看一下Db類的信息。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
類的注釋

通過上圖我們可以看到關(guān)于Db類的一部分信息,就是使用Db類的一些查詢方法。

但是來到Db類的最后可以看到一個(gè)熟悉的方法__callStatic。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
調(diào)用沒有聲明的靜態(tài)方法

這個(gè)方法在一直讀咔咔文章的讀者應(yīng)該已經(jīng)很是熟悉了,這個(gè)方法在門面源碼解析那一節(jié)中進(jìn)行過深入的了解。

對于這個(gè)方法只需要記住的是在調(diào)用沒有聲明的靜態(tài)方法時(shí)會(huì)進(jìn)行調(diào)用。

至于call_user_func_array這個(gè)函數(shù)的使用可以理解為,這個(gè)方法是內(nèi)置函數(shù),可以直接調(diào)用函數(shù)運(yùn)行,也就是可以直接運(yùn)行方法。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
門面類的源碼

在通過剛剛的查看Db類的注釋信息時(shí)可以看到Db類是使用著Connection這個(gè)類,也就是連接數(shù)據(jù)庫類。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
連接數(shù)據(jù)庫類

進(jìn)入到這個(gè)類里邊簡單的看一下構(gòu)造函數(shù)即可,至于是怎么一個(gè)運(yùn)行順序會(huì)在下文進(jìn)行講解。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
數(shù)據(jù)庫配置數(shù)組創(chuàng)建Builder對象

在框架中操作控制器有倆大場景,第一中為Db類操作,第二種就是Model操作。

其中Connection·為連接器,Query為查詢器,Builder為sql生成器,exception為異常類。

知道了以上的幾個(gè)信息,在接下來的理解過程中會(huì)有一定的幫助,在下一節(jié)中將會(huì)對Db類庫場景分析。

二、Db類庫場景分析

先從一個(gè)簡單的案例進(jìn)行解析,先來看一下數(shù)據(jù)庫的數(shù)據(jù)。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
數(shù)據(jù)庫模擬數(shù)據(jù)

然后來到控制器寫一個(gè)簡單的查詢案例,在創(chuàng)建控制器之前先使用命令進(jìn)行創(chuàng)建一個(gè)測試控制器。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
創(chuàng)建的測試控制器

在這個(gè)控制器進(jìn)行簡單的查詢數(shù)據(jù)。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
使用簡單的案例進(jìn)行查詢數(shù)據(jù)庫數(shù)據(jù)

查詢結(jié)果如下

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
查詢結(jié)果

在這個(gè)案例中,可以看到使用的是Db::query這種查詢方式,接下來對于這種查詢方式進(jìn)行簡單的剖析。

接著執(zhí)行流程就會(huì)來到Db這個(gè)類,在這個(gè)類中可以看到關(guān)于當(dāng)對象訪問不存在的靜態(tài)方法時(shí),__callStatic()方法會(huì)被自動(dòng)調(diào)用。

這個(gè)方法在之前門面的講解中進(jìn)行了深度講解。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
Db類中的靜態(tài)調(diào)用方法

從上圖可以看到當(dāng)執(zhí)行訪問對象不存在的靜態(tài)方法時(shí)會(huì)執(zhí)行到call_user_func_array調(diào)用回調(diào)函數(shù),并把一個(gè)數(shù)組參數(shù)作為回調(diào)函數(shù)的參數(shù)

接著代碼就會(huì)執(zhí)行到static::connect()這行代碼,由于本類Db沒有繼承任何的類,所以對于static這個(gè)的使用就是調(diào)用本類。

如果當(dāng)Db類繼承了其它類那么就會(huì)有一定的區(qū)別,這個(gè)區(qū)別就是關(guān)于static關(guān)鍵字,給大家做的一點(diǎn)點(diǎn)冷門知識(shí)得補(bǔ)充,當(dāng)一個(gè)類繼承一個(gè)類時(shí),在父類實(shí)用static關(guān)鍵字時(shí),默認(rèn)調(diào)用的子類的方法。

切換數(shù)據(jù)庫連接

因?yàn)闆]有任何繼承,所以會(huì)來到本類的connect這個(gè)方法。

在這個(gè)類里邊首先會(huì)返回結(jié)果為數(shù)據(jù)庫配置信息。

然后會(huì)從配置信息中獲取到query這個(gè)索引,最終返回thinkdbQuery這個(gè)字符串,這里一定要注意返回的是字符串,不是這個(gè)類的實(shí)例。

緊接著就會(huì)執(zhí)行到第三步創(chuàng)建數(shù)據(jù)庫連接對象實(shí)例,接下里將會(huì)對這一步進(jìn)行解析。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
切換數(shù)據(jù)庫連接

緊接著會(huì)來到文件實(shí)際執(zhí)行的為 new thinkdbQuery,最終會(huì)返回執(zhí)行查詢 返回?cái)?shù)據(jù)集,返回?cái)?shù)據(jù)為返回 object(thinkdbQuery)

關(guān)于這個(gè)$this->connection是在本類的構(gòu)造函數(shù)進(jìn)行設(shè)置的。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
執(zhí)行查詢 返回?cái)?shù)據(jù)集

先簡單的看一下這個(gè)構(gòu)造函數(shù),在這個(gè)構(gòu)造函數(shù)中直接就設(shè)置了connection這個(gè)屬性的值,所以在上圖中可以使用。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
設(shè)置連接

在這里執(zhí)行完成之后就會(huì)將返回的值給從一開始就解析的這個(gè)調(diào)用未聲明的靜態(tài)方法會(huì)進(jìn)行調(diào)用。

其中static::connect()就是最終返回的值static::connect() 返回 object(thinkdbQuery)。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
靜態(tài)方法調(diào)用

所以接下來代碼會(huì)執(zhí)行到 ?thinkphp/library/think/db/Query.php 的 query方法

$sql 就是在Db::query()中傳遞的sql語句,并且執(zhí)行查詢 返回?cái)?shù)據(jù)集

最后這段代碼會(huì)執(zhí)行thinkdbconnectorMysql的query方法

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
執(zhí)行查詢 返回?cái)?shù)據(jù)集

接下來來到thinkdbconnectorMysql的query方法

在這個(gè)方法中主要做了三件事情。

  • $this->initConnect 初始化數(shù)據(jù)庫連接
  • $this->PDOStatement->execute(); 執(zhí)行查詢
  • return $this->getResult($pdo, $procedure); 返回結(jié)果集
ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
執(zhí)行查詢 返回?cái)?shù)據(jù)集

解析$this->initConnect 初始化數(shù)據(jù)庫連接

在這個(gè)方法中可以看到是進(jìn)行了一次配置信息獲取,首先需要明白這個(gè)配置信息是什么。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
初始化數(shù)據(jù)庫連接

這個(gè)配置項(xiàng)是在配置文件database中配置的,根據(jù)注釋提供的信息可以看到主要是關(guān)于主從服務(wù)器設(shè)置的。

一般情況下是不會(huì)在框架中配置主從信息的,這里就不去解析框架是如何實(shí)現(xiàn)數(shù)據(jù)庫的主從配置了。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
數(shù)據(jù)庫部署方式:0 集中式(單一服務(wù)器),1 分布式(主從服務(wù)器)

在這個(gè)判斷中在進(jìn)行了一次判斷當(dāng)前數(shù)據(jù)庫連接的id,然后執(zhí)行了連接數(shù)據(jù)庫方法。

這個(gè)方法最終會(huì)返回object(PDO)#33的一個(gè)實(shí)例信息。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
連接數(shù)據(jù)庫方法

$this->PDOStatement->execute(); 執(zhí)行查詢

第二件事情做的就是執(zhí)行查詢,接下來我們來詳細(xì)說明一下這個(gè)到底是如何執(zhí)行的。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
執(zhí)行查詢

在返回pdo實(shí)例時(shí),將這個(gè)實(shí)例賦值給了$this->PDOStatement這個(gè)屬性,所以會(huì)去PDO類中進(jìn)行執(zhí)行。

在這里大家需要明白一件事情就是關(guān)于execute這個(gè)方法,用于執(zhí)行返回多個(gè)結(jié)果集、多個(gè)更新計(jì)數(shù)或二者組合的語句。

第三件事情返回結(jié)果集

直到這里就是執(zhí)行的最后一步就是返回結(jié)果集。

這里使用的方法都是查詢底層,就在去解析了,在這里就會(huì)返回最終查詢結(jié)果。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
獲得數(shù)據(jù)集數(shù)組

最終結(jié)果就會(huì)返回給這里__callStatic方法,并且返回給上層的$res變量。

ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
測試案例
ThinkPHP數(shù)據(jù)庫查詢之Db類場景分析
最終查詢結(jié)果

直到這里關(guān)于使用Db查詢的執(zhí)行流程就解析完了, 但是框架給封裝的方法不僅僅只有query,其它的查詢方式可以按照咔咔的這個(gè)流程在進(jìn)行簡單的分析。

最后執(zhí)行的都會(huì)是這一節(jié)的最后幾個(gè)流程,只是前邊執(zhí)行會(huì)有一點(diǎn)點(diǎn)區(qū)別而已。

堅(jiān)持學(xué)習(xí)、堅(jiān)持寫博、堅(jiān)持分享是咔咔從業(yè)以來一直所秉持的信念。希望在偌大互聯(lián)網(wǎng)中咔咔的文章能帶給你一絲絲幫助。我是咔咔,下期見。

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