“
在上文聊到了thinkphp數據庫查詢Db方式,今天來簡單的聊一下關于Model類的實現方式。
”
前言
Model也就是框架中提到的模型概念,這種使用方式在框架使用中占了絕大部分。
接下來咔咔將會在上文的基礎上再繼續對模型進行深度解析,所以現在準備好小板凳嗑點瓜子來閱讀本文吧!
上文給大家提供的Db類的執行流程流程圖也給大家放出來,可以在熟悉一下。
一、簡單看一眼模型的一些使用文件
在模塊的目錄下肯定是要存在model目錄的
然后來到框架的底層可以看到關于模型類的文件,在這個類中使用了倆個之前咱們學習過的知識點。
第一個就是ArrayAccess像訪問數組一樣訪問對象的屬性。
第二個為超類(trait)這個特性,其實就是實現了一個類似多繼承的一個功能,但是切記PHP是沒有多繼承的,這倆種概念是不能混淆的。
然后在框架的底層也存在一個model文件夾,這個文件夾中也是使用了跟Db類一樣的功能。
例如 連接器,查詢器,生成器
經過簡單了解之后我們就需要對模型中的一個案例進行解析了,只是針對一個案例的實現哈!
二、模型場景分析之新增邏輯源碼解析
本案例使用模型中的新增作為案例的分析,并且對源碼進行深度解析。
首先需要先創建出來模型文件,咔咔在創建文件這里一直都是使用的命令行進行創建的,使用命令行創建文件方式的好處就是防止自己創建文件時對于命名空間會出錯。
然后實現第一個功能使用模型進行新增,這塊的內容真的是很簡單,咔咔簡單幾步就過了這都是特別基礎的了,咔咔主要工作還是給大家解析實現過程。
控制器中的案例如下,這里注意一下咔咔的寫法。
簡單說一下咔咔為什么要這么寫,這樣寫的好處是什么。
首先是引入模型類這個是必不可少的。
然后聲明了一個變量
最后一步是在控制器初始化的時候將模型類賦值給了聲明的變量。
然后使用的時候就使用聲明的那個變量即可,這樣做的好處就是當你的模型名后期發生沖突時可以減少修改的代碼量。
你可以想一下這樣一個場景,你預先定義了一個模型名,然后在后期又想將這個模型名進行改動,這個時候如果按照咔咔的這樣的寫法,你只需要控制器初始化中的內容,也就是一行代碼搞定。
否則整個代碼都需要修改,這也就是咔咔為什么要這樣寫。
先來執行一下,看一下執行結果。
根據上圖結果可以得知代碼邏輯沒有任何問題,接下來將會對save這個方法進行深度解析,看模型跟Db類的執行方式有什么不同。
深度解析save方法
首先你要明白這段代碼會執行到那個文件里邊。
都明白這個$this->userModel是模型中的類的對象,那么就直接去這個模型文件里邊看一眼。
其實這個文件看不看都沒關系,咱們自定義的模型文件肯定是繼承的Model文件,也就是在本文一開始咔咔帶大家看的那些關于模型會使用到的文件。
那么就來到框架底層的模型類thinkphp/library/think/Model.php。
看到這個方法是不是應該明白一點點東西,就是不去看文檔也應該一下明白,當save方法只有一個參數的時候就是新增,當存在第二個參數時就是更新。
由于咔咔的案例中給的參數就是一個數組,所以第一個判斷就不會執行。
接下來將對這個save方法中的寫入之前檢查數據進行深度解析。
接下來看一下這個方法都進行了什么操作。
根據上圖可以得知傳遞過來的參數就是數組,也就是我們需要新增的數據。
在上圖中最重要的一個步驟就是這行代碼$this->setAttr($key, $value, $data);
根據提示咔咔來到這個方法,三個參數的值也已經打印出來,所以判斷都不會進行執行,只會走最后一步,設置數據對象屬性。
根據上圖最終返回結果會直接返回到$this->checkBeforeSave($data, $where),也就是下圖。
接下來關于$result = $this->exists ? $this->updateData($where) : $this->insertData($sequence);這行代碼就需要該好好理解一下了。
首先可以看到第一個屬性那就是$this->exists,這個值熟悉不,沒錯,就是在寫入之前檢查數據時如果存在where條件則會設置為true,請看下圖
所以說代碼會執行$this->insertData($sequence)這個方法,在這方法中咱們什么都不去關注,主要關注是怎么添加數據的就行了。
也就是關注咔咔圈起來的地方即可。
接著代碼會來到insert這個方法,在這個方法中$this->parseOptions();這里就是之前分析的分析表達式(可用于查詢或者寫入操作)這塊內容。
在這里就使用了連接器,這個連接器就是在本類的構造函數通過依賴注入的方式注入進來的對象。
然后就會來到thinkphp/library/think/db/Connection.php這個文件的insert方法。
接著會調用execute方法進行執行SQL語句,因為在這之前已經將sql語句生成好了,在下文將重新起一個小節深度解析這個方法。
通過builder類生成SQL語句然后獲取綁定的參數 并清空最后使用執行操作,執行sql語句
三、深度解析execute的執行
案例依然是上節使用的案例
首先得明確一下execute這個方法的參數,在這個方法存在三個參數,主要說明第一和第二個參數。
參數的值咔咔已經放到了代碼注釋中。
然后一步一步的分析,首先執行的是$this->initConnect(true);初始化數據庫連接。
在這個方法中需要知道的是,這里到底判斷的是什么,其實也就是deploy這個參數是什么。
首先需要明確的是這個參數肯定是從配置文件中獲取出來的,然后咱們現在在解析的是數據庫,那么這個參數有很大的可能就是在數據庫的配置文件。
在對代碼的分析下我們在數據庫的配置文件中找到了這個配置項,這個配置項是數據庫的部署方式。
0 集中式(單一服務器),1 分布式(主從服務器),在本案中,或者在真實項目運行中也不會在框架中使用分布式數據庫,所以就不用去了解了。
然后代碼就會繼續執行$this->linkID = $this->connect();,也就是注釋給的提示為默認單數據庫。
來到這個方法中,咔咔截圖截到的地方會進行數據庫連接ID 支持多個連接的判斷。
然后第二個判斷會直接獲取參數配置信息和本類的構造函數中提前獲取的到的數據庫配置文件,并且最后返回給config屬性。
接下來解析連接參數這塊的內容,這塊的內容,判斷配置信息中的params索引值,這個值在配置文件是一個空數組,所以是返回true的。
第二個判斷是否為數組同樣也會返回true。
所以說這個判斷條件成立,會執行if的判斷語句。
在這里說一個小的知識點就是關于運算符與或非的知識。
與:所有的條件都為真返回true
或:只要有一個條件為真則返回true
上圖中的本類屬性params已經提前聲明好了,這里只需要這是pdo連接mysql時需要的參數即可。
為了方便大家理解咔咔將這個參數給大家打印了出來,請看下圖。
也就說關于pdo參數其實就是聲明的一系列常量而已。
接下來就是重中之重了,也就是使用pdo的方式進行連接數據庫,并且將連接信息返回回去,也就是返回給$this->linkID,直到這里初始化數據庫連接就結束了。
然后就會使用PDo的操作實例執行execute這個方法是內置的方法,最終返回或者影響記錄數。
四、總結
本節從認識模型需要的文件然后在對模型的添加行為做了深度的源碼解析行為。
在解析源碼的過程中有的部分沒有進行完全的講解,但是重點的部分都已經過了一遍。
最后在深度解析了execute這個方法,為什么要解析這個方法,因為這個方法是所有操作執行的最后一步。
“
堅持學習、堅持寫博、堅持分享是咔咔從業以來一直所秉持的信念。希望在偌大互聯網中咔咔的文章能帶給你一絲絲幫助。我是咔咔,下期見。
”