“快取在專案的運行了一段時間都會使用的一個功能,本文將會對框架中的快取做一個深度的解析
”
#在專案中快取是不可或缺的功能,當使用者量大的時候是必須上快取的,如何都直接查資料庫那麼對於使用者體驗來說就太差了。
那麼什麼情況下應該要使用快取呢!
以上說的這些應用程式場景並不說是框架的緩存,一般在使用緩存的層面是不太使用框架的緩存的。
常用的為redis,memcache等NoSQL。
但是今天主要討論的是框架中緩存,所以千萬不要認為框架的緩存是無所不能的,還是要看項目的實際情況。
首先需要實作以下的案例,並且引入cache類別
cache怎麼運作的?
就程式碼Cache::set
這個現在知道是怎麼運行的嗎?如果不知道咔咔帶你在來深入的學習一次。
我們都知道框架的入口檔案是index.php,在入口檔案中引入了一個檔案為base.php。
來到base.php這個檔案裡邊可以看到關於註冊類別庫別名,至於是怎麼註冊的,這個在框架執行流程的那一節有過深度的講解,可以回過頭在去了解一下。
所以說程式碼將會執行到框架核心的facade這個類別裡邊,在這個類別裡邊存在一個方法__callStatic,當呼叫不存在的靜態方法時此方法會進行執行。
那麼怎麼來做這個驗證呢!不能喀喀這樣說就是這樣的對吧!
那麼程式碼將會接著來到創建Facade實例這個方法,我們做的測試就是將這個class印出來得到的值都有什麼。
暫時先不管這個cache執行了幾次,是可以明顯的看到列印結果是存在這個值的,所以說從另一個笨拙的方面驗證了咔咔的說辭。
這裡有一個特別小的細節我想大家應該要了解一下,那就是關於static的使用
關於static的小技巧
首先可以看到cache類別是繼承這Facade門面類別
然後static是在門面類別中做的使用,那麼最後回傳的類別就是繼承門面類別的那個類別也就是cache類別
總結為一句話就為
static 如果有被繼承的話預設呼叫子類,否則呼叫的是自身
##所以說下邊接著的static::getFacadeClass()這裡也是執行的子類別中的方法。
好了,進入了一段小插曲,接下來會到正題。
所以說程式碼將會執行到thinkphp/library/think/Cache.php
這個文件,也就是核心類別庫的位置。
在這個方法你是找不到set方法的,所以程式碼將會執行到__call方法,這個方法當呼叫不存在的方法時則會觸發的方法。
自動初始化快取
根據執行流程我們將會看到init這個方法自動初始化快取(這裡要注意,第一次不是在這裡進行執行的,而是ThinkPHP快取原始碼深度解析,當ThinkPHP快取原始碼深度解析執行完後會把值存放在handler這個屬性,第二次透過call方法進來之後就直接返回了,而不會在進行一次執行,這裡一定要注意)
在這裡我們進行一次列印$options
這個的值。
探討為什麼$options這個參數會有值
這裡就是關於容器方面的知識了,來喀喀帶你看一下。
當在建立Cache時建立Facade實例,在這個過程中註意咔咔下圖圈起來的部位,執行了一個見了八百次的ThinkPHP快取原始碼深度解析了。
來到ThinkPHP快取原始碼深度解析只需要看喀喀爾的地方即可
然後在進入到invokeClass
方法,這個方法是呼叫反射執行類別的實例化支援依賴注入。
在這個方法中透過反射執行了Cache中的ThinkPHP快取原始碼深度解析。
所以就會執行Cache類別中的ThinkPHP快取原始碼深度解析,這個方法就會進行實例化本類,並且執行建構函數,接下來看一下。
來到建構子中你會看到從ThinkPHP快取原始碼深度解析取得到的cache設定檔的設定項傳遞到了init方法,也就是自動初始化快取的部分。
所以從這裡看到init方法自動初始化快取第一次執行是在容器實例化的時候執行的所以 $options
才會存在值。
接下來會沿著這個流程進行連線快取也就是程式碼$this->handler = $this->connect($options);
這塊的內容。
這個方法就很簡單了,就是使用了之前一直講解的工廠模式實作的載入不同類型的快取方式。
接著會把回傳的物件存放在以$options
md5為下標的快取實例屬性$instance
裡邊。
最終程式碼會傳回cache中的__call方法,類別為object(think\cache\driver\File)
方法為set
於是執行流程會來到下圖位置寫入快取
取得檔案名稱
在這個方法中主要需要理解的一件事情就是在快取中是如何進行獲取具體的檔案名稱然後進行儲存資料的。
這個name值就是咱們需要設定的值,wechat。
然後來到getCacheKey取得變數的儲存檔名。
在這個方法中第一步就是透過hash的方式進行型別和快取值加密,這個options是在本類別宣告好了的,這裡一定要明確。
因為框架中大量的使用了options這個變數千萬不要搞混淆了。
在這個方法中需要明白的就是這個檔名是怎麼確定的。
還是要來到本類別的開始位置檢視一下這個options的值,在這個類別中可以看到上圖中使用的加密類型為hash_type就是md5
##然後來到建構函式中可以看到關於path的設定 在上圖中可以看到Container::get('app')這行程式碼,這行程式碼就是使用的容器執行的也是ThinkPHP快取原始碼深度解析,關於這個ThinkPHP快取原始碼深度解析在容器中扮演的角色是十分大的,所以需要好好理解。
這時可以查看一下建立的文件,可以看到文件已經建立好了。
最後透過file_put_contents函數將資料存放至剛剛取得的快取檔案存放位置
資料庫儲存形式就是下圖
直到這裡關於框架快取設定就結束了,其實流程並不難,在這個案例中咔咔使用的檔案形式的,至於redis還是其它都是一樣的。
既然學習了快取設定的原始碼解析,那麼也應該來簡單的了解一下快取所取得的源碼解析。
同樣示範案例還是之前的那個,只不過是把set換為get即可
跟設定快取的流程是一樣的,首先會來到門面類別中建立快取的對應實例
門面類別創建了快取類別的時候之後就會來到cache類別這個檔案thinkphp/library/think/Cache.php
#在這個檔案中可以看到還是使用了__call方法,這個方法就是呼叫不存在的方法會執行。
接著會來到這init方法,這個方法在設定快取值的時候已經進行深入講解了。
根據執行流程我們將會看到init這個方法自動初始化快取(這裡要注意,第一次並不是在這裡進行執行的,而是ThinkPHP快取原始碼深度解析,當ThinkPHP快取原始碼深度解析執行完後會把值存放在handler這個屬性,第二次透過call方法進來之後就直接返回了,而不會在進行一次執行,這裡一定要注意)
這裡為什麼先會執行cache的ThinkPHP快取原始碼深度解析,是因為在容器中建立cache類別實例的時候會在ThinkPHP快取原始碼深度解析中判斷類別中是否存在ThinkPHP快取原始碼深度解析,如果存在就會先執行。
所以說在cache這個類別中return call_user_func_array([$this->init(), $method], $args );
這塊程式碼會去執行thinkphp/library/think/cache/driver/File.php
這個類別的get方法
getCacheKey
然後可以接著往下看,這裡有一個過期刪除快取檔案。
框架中的過期策略是當你設定了過期時間時,快取過期後不會直接刪除而是當你再一次造訪之後才會進行刪除。
這種策略就是redis中的惰性刪除,當我們使用惰性刪除時,資料到期了也不會自動刪除,那麼他的刪除方式是,在下一次在取得這個key值時,會做一個判斷,判斷這個key是否過期,如果過期了在執行刪除。
截止到這裡關於快取取得的執行流程已經原始碼解析就完成了,其實大多數內容在取得的時候就已經解析完了。
那為什麼還是要在聊一下取得快取數據,那是因為這裡還需要給大家在解釋一些東西。
#在設定快取的時候將快取的值寫入檔案時有過一個函數gzcompress
然而在取得快取值的時候從檔案將資料讀出時又遇到的一個函數gzuncompress
其實從設定快取和取得快取的這兩個功能中就可以看出,設定的為壓縮數據,所取得的解壓縮數據。
在PHP中關於壓縮函數還有其它兩個分別為gzdeflate、gzencode
,同樣的解壓縮函數也是對應的gzinflate gzdecode
#這幾個函數雖說都是壓縮函數,但是底層實作是不一樣的。
gzcompress使用的是ZLIB格式;
gzdeflate使用的是純粹的DEFLATE格式;
gzencode使用的是GZIP格式;
以上就是關於資料壓縮和解壓的一些知識,了解即可。
#在這一節中咔咔帶大家領略了框架對於快取的處理結果。
其實咔咔之前測試過關於框架自帶的快取回應時間應該會縮短三分之一,當然這個也是根據資料量的大小有區別的。
至此關於PHP框架ThinkPHP的原始碼解讀這裡就結束了,後期如果有時間將會對其中一些沒有提到的內容在進行解讀。
最後說一句閱讀原始碼是真的累。
「堅持學習、堅持寫博、堅持分享是咔咔從業以來一直所秉持的信念。希望在諾大互聯網中咔咔的文章能帶給你一絲絲幫助。我是咔咔,下期見。
”
以上是ThinkPHP快取原始碼深度解析的詳細內容。更多資訊請關注PHP中文網其他相關文章!