面試官:聊一下對框架配置載入的理解吧!
❝在上期聊了ThinkPHP類的自動載入,如你還不太瞭解可以跟這下文連結去進行檢視。本文會帶你一起解讀ThinkPHP配置檔案。
❞
前言
想了很久終於要開始系列文章的編寫了,期望是寫出提升和麵試都可以搞定的系列文章。
當你看到本文時,如果你發現咔咔沒有編寫到的面試熱點問題或者技術難點,期待評論區指出,一起完善。
第一期文章:ThinkPHP自動載入Loader原始碼分析 第二期文章:ThinkPHP配置原始碼分析
一、配置檔案的種類
在ThinkPHP中有四類配置檔案,你知道多少呢!不知道也沒關係咔咔帶你在看一次。
這四種配置檔案分別為慣例配置、應用配置、模組配置、動態配置。
在這裡需要說明一下,一般開發中慣例配置和動態配置是不會去使用的,尤其動態配置更不會去使用。
動態配置是直接使用Config::set("設定動態配置檔案")來進行設定的,所以這個東西不要去用,一定不要去用,否則專案後期怎麼去管理。
關於這四類配置檔案咔咔直接用一幅圖來給大家展示,就不過多說明了,本文的重點不是給大家介紹這玩意。
關於ThinkPHP5.1取消了單獨的config檔案,將應用配置修改到config下的app.php檔案中。
新增了模組配置,模組配置也是在config目錄下,例如你在app目錄下有倆個模組,分別為index、admin這倆個模組,那麼就可以直接在config目錄下建立admin、index目錄,然後建立對應模組的配置檔案即可。
這四種配置檔案的優先順序就是上圖的排列順序,管理配置、應用配置、模組配置、動態配置
二、學習使用ArrayAccess
在檔案thinkphp/library/think/Config.php
,類Config實現了一個介面為ArrayAccess
。
這個時候你是不是有疑問了,這個類到底是幹嘛的,為什麼要去了解和學習它!帶著這個疑問繼續往下探尋答案吧!
到這個接口裡邊一探究竟。
在這個接口裡邊有四個介面需要實現分別為
offsetExists 檢測偏移位置是否存在 offgetGet 獲取一個偏移位置的值 offsetSet 設定一個偏移位置的值 offsetUnset 刪除一個偏移位置的值
這幾個函式放到這是不是有點懵呢!彆著急,這就給你解答
這幾個方法在Config中也進行實現,但是裡邊使用了幾個方法,根據上邊對方法的作用說明後。
像set、has、remove、get想想大家就知道是什麼意思了。
接下來,咱們自己來實現一下這個類,給大家演示一下這個類用處到底是什麼。ArrayAccess這個類不僅是TP大量使用,在laravel中也是大量存在,所以需要好好學習這個類的作用和思想。
需要在kaka目錄下建立一個檔案TestArrayAccess
檔案,並且設定一個屬性,在實現ArrayAccess類。
至於我自己建立的這個資料夾kaka
為什麼會執行自動載入就是上一期在類的自動載入中實現的。
如若不會的話可以把檔案先放置到extend目錄下即可。
接著來到application/index/controller/Index.php
控制器使用上圖實現的方法
列印結果
這裡在使用offsetGet
列印的結果為kaka
應該都明白怎麼回事了吧!其餘倆個方法就不去演示了,相信你也已經明白了。
所以說這個ArrayAccess類就是提供像訪問陣列一樣訪問物件的介面
。
三、瞭解Yaconf
估計有同學知道Yaconf就是我們牛逼克拉斯的鳥哥寫的。
咔咔瞭解Yaconf後,總結推出這個開源的幾點原因。
配置檔案過多,導致載入時間過長 配置檔案可讀性差,需要執行解析 配置檔案與程式碼同屬一個專案部署在一起會有安全隱患,同時如果配置檔案修改時還需要走上線流程 加大運維與開發協同難度,如果運維需要修改MySQL或者其它配置也需要通知開發進行同步修改
那麼在來說一下使用Yaconf的優點
不跟程式碼在一起,使用專屬的配置目錄 PHP啟動時,載入完所有的配置,進行常駐記憶體,伴隨著PHP的生命週期存亡,避免每次請求時解析配置檔案,消耗時間 配置檔案跟程式碼分離,就可以藉助配置後臺管理來統一管理配置資訊 配置檔案如有發生變化時會進行過載(這裡給的建議是使用mv而非cp) 支援型別豐富,例如:字串、陣列、分節、並且還可以在PHP配置檔案裡邊直接使用PHP的環境變數和常量 最後一點就是使用非常簡單
在瞭解了Yaconf可以做什麼的時候之後,在去開始下一步的操作,別一上來就是安裝、配置、呼叫,然後一頓操作結束後,不知道是幹嘛的,那樣就沒有任何意義了。
接下來將會介紹在win、linux上安裝並且使用
四、Yaconf在window上安裝
點選後邊的DLL,選擇對應的版本
選擇適用的版本
如何判斷什麼版本適合自己,對照著我圈起來的幾個地方去下載就對了
然後將這個檔案放置到PHP的擴充套件目錄裡邊 修改配置檔案
extension=php_yaconf.dll
[yaconf]
yaconf.directory="D:\phpstudy_pro\WWW\yaconf"
yaconf.check_delay=60
重啟環境,然後檢視一下就ok了。
這裡需要注意一點就是在複製的時候難免會有一些空格什麼亂七八糟的東西,切記刪除乾淨,否則你會知道什麼叫難以啟齒的柔弱。
五、Yaconf在window上使用
此時就直接在Yaconf的目錄中建立一個ini檔案,並且寫上如下內容
控制器直接讀取
經過打印出來的結果也是預期的值
檔案如有改動,則直接重啟ngixn即可
Yaconf提供的另外的一個介面為\Yaconf::has
以上就是Yaconf在window上的使用,使用起來還是相對簡單的。
這裡有一個注意點就是修改了Yaconf的配置檔案之後我們需要重啟web伺服器。
六、Config原始碼剖析
雖說上面的Yaconf對於config的原始碼解析沒有多大的幫助,但是也是在擴寬一下思路,以後在工作中可以嘗試使用Yaconf。
進入正題,想知道Config是怎麼進行載入解析的,先來畫一個圖。一起看一下載入config的執行流程。
回到public/index.php
,在上一期說了類的自動載入是在載入base.php檔案的過程中執行的。
那麼config的載入是在下圖框起來的這裡,這裡涉及到了容器,會有一個單獨的專題來對容器進行剖析。
這裡就不過多說明了,這段程式碼回去執行`D:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\thinkphp\library\think\App.php這個檔案的run方法。
並且在run
方法中需要追蹤的是initialize
應用初始化這個函式
接著在initialize
這個方法中就會看到配置檔案的蛛絲馬跡,隨之而來就是一個初始化應用init
直到走到init方法中,才算是進入了主題。
開始了自動載入配置檔案,並且還呼叫了config類中的load方法,也是需要一起閱讀的。
來到這裡之後需要簡單的進行解讀一下
這段程式碼會直接走到elseif中,因為在app目錄下沒有設定config目錄
並且這裡有個configPath這個屬性熟悉吧!這個值最終就是D:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\config\
在接這就是把config目錄下的檔案全部拿出來。
傳遞給config類的load方法
在這裡有幾個知識點提一下,就當回顧了
scandir :以升序的方式返回一個目錄下的所有檔案,還有第二個引數1,表示降序的方式返回一個目錄下的所有檔案。 pathinfo:以陣列的形式返回檔案資訊,分別為目錄名、檔名、副檔名,其中的幾個引數程式碼中有提到,可以看下圖即可。
在這段程式碼中有一個屬性configExt,這個值是在環境變數讀出來的,給的值是php
緊接著就需要來到thinkphp/library/think/Config.php
這個檔案了,在app檔案中最後呼叫了config類中的load。
一起來看看都經歷了什麼
在load這個方法中,流程的最終走向會到loadFile
這個方法中,至於elseif的程式碼為什麼不會走,或者說這段程式碼就是多餘的。
因為當Yaconf安裝後在PHP啟動後就會直接去載入對應的配置檔案
來到loadFile這個檔案後
我們都知道在ThinkPHP框架中,config目錄下的所有檔案都是PHP型別的
所以在判斷了型別後就直接進入到set裡邊進行資料的處理
include直接引入的就是config目錄下的配置檔案,並且所有的配置檔案都是直接return返回一個數組
在set方法中,這塊程式碼就是核心了
一直迴圈合併陣列,最終把所有的配置資訊都返回給了config這個屬性
截止到這裡config目錄下的所有配置就載入完成了。
以上就是config的載入流程,其實當你閱讀完之後感覺也沒有那麼的難,就是編碼技巧和思想。
而我們閱讀原始碼不是看它程式碼怎麼寫的,是學習的它的編碼思想,最終落地到我們自己的專案中。
七、工廠模式載入其它型別的配置檔案
在之前看到的loadFile方法中,檔案型別為PHP或者yaml程式就打斷了,就不會在去執行後邊的pares方法。
那麼這個parse方法是做什麼的呢!
進入到paras這個方法後,首先看註釋
隨後使用了一個工廠模式去載入think/config/driver下的檔案
進入到factory這個方法後,這塊內容屬於容器的就不過多解釋了。
只需要知道這裡最終會返回一個例項給paras
方法的$object變數
最終還是使用在上文中提到的set方法,而內部的object->parse()就是執行返回物件的內部方法,例如下圖展示三個型別。ini、json、xm三個型別都存在同樣的方法
這是ini型別,其它倆個的型別也是一毛一樣的,就是會有同樣的方法來實現對應的功能
「簡單梳理一下工廠模式載入不同型別的配置」
把對應的型別傳給一個方法 然後這個方法返回對應的例項 在用這個例項去呼叫類裡邊的方法 所有例項裡的方法名都是一致的
這裡咔咔後期會單獨出一篇文章模仿這個實現另一個功能,導圖會有所有的文章連結哦!
在ini.php中看到了一個方法parse_ini_file
,其實這個方法根據之前的學習就大概能瞭解到時把ini型別的配置檔案轉為陣列形式。這裡就不做演示了,很是簡單哈!
那麼其它倆種類型都是為了把檔案資料轉為陣列的。
八、yaml初體驗
yaml就是一個類似於xml、json資料通訊方式,但是yaml是以資料為中心,而非標記語言為重點。
這裡提到yaml是因為在框架原始碼中提到了這個,後邊的流程也是需要走yaml,所以還是需要簡單的瞭解一下哈!
安裝yaml,直接到pcel裡搜尋yaml,下載對應的版本即可。下載方式跟之前yaconf安裝一樣的。
安裝成功後就會在PHP中存在這個擴充套件。
這裡需要注意的是需要在php.ini中把yaml擴充套件檔案加進去哈!
如果不會就去Yaconf在window上安裝那一欄去看是怎麼安裝的,安裝那個流程就可以了。
安裝完成後就是簡單的使用了,在config中新建一個kaka.yaml檔案。
並且寫上如下的內容,切記在yaml中冒號後邊需要空一格,yaml寫法就不過多說了,畢竟平時不怎麼用。
這裡說明只是為了閱讀框架程式碼而做的工作。
測試yaml資料讀取
讀取出來的資料就是一個數組,也就是說把yaml格式的資料轉化為陣列形式。
這個方法是從哪裡知道的呢!
還記得在config類下loadFile方法中,根據檔案擴充套件的不同載入不同形式的方法。
PHP型別的直接就走了set,yaml型別的把資料處理為陣列後執行set方法
如果是其它型別的話就會在上邊說的工廠模式返回對應類名的例項,並執行對應類裡邊的方法將格式都轉化為陣列形式。最終還是使用set方法
其它型別的配置檔案最終都會走到set方法裡邊。
九、如何讓框架載入其它型別的配置檔案
在初始化應用和模組中有一個屬性是configExt,這個屬性就是檔案的擴充套件
去找一下這個屬性是在哪裡設定的。
根據config配置檔案載入流程,可以很清晰的看到init
方法的上一層是初始化應用,也就是initialize
方法。
那麼這個屬性肯定是在init
方法之前就已經提前設定好了的。
返回到init
方法的上一層initialize
就直接可以看到這個值的設定。
這個值是從env的環境變數中獲取的,如果沒有則預設為php,所以就需要建立一個env的檔案。
並且給一個預設值為yaml
這裡給大家看一下變化,在5.1.34 LTS版本的時候存在一個bug,咔咔目前使用的是5.1.39 LTS 這個問題已經修復了。
這段程式碼相信都可以看出來,它是先對configExt進行了設定預設值,然後在去載入環境變數配置檔案。
那麼載入這個環境變數的這段程式碼就毫無任何意義,configExt的值永遠都是.php
就算在env檔案裡邊做了配置也不會獲取得到。
在之前在config配置檔案中添加了一個yaml的配置檔案
那麼這個時候就可以使用config類來獲取yaml型別檔案的配置了。
測試一下沒有任何問題,資料是可以出來的。
但是實際專案中可不敢這麼整啊!如果要把configExt
這個值配置到環境變數,配置的是什麼型別就需要把config目錄下的所有配置檔案全部轉化為對應型別。
例如configExt設定的為.ini ,則就需要把config目錄下的所有檔案都改為ini檔案形式
這塊內容只是針對閱讀原始碼後一個運用而已,實際專案中不要這樣使用,因為在tp框架中所有的配置檔案都是PHP型別的。
如果改為其它型別的話,就需要修改框架中所有的配置檔案,這種事情能不幹就不哈!
十、框架底層配置載入程式碼優化
在thinkphp/library/think/Config.php
中方法loadFile這裡看起來是不是有點不太優雅了。
既然在方法最後使用parse
方法,也就是之前提到的工廠模式載入其它型別的配置檔案。
那麼為何不讓這個工廠模式也載入PHP和yaml型別的配置檔案。
此時就需要在thinkphp/library/think/config/driver
這個目錄建立php檔案和yaml檔案了。
首先建立一個php檔案。
並且仿照其它三個型別檔案,在php檔案型別中只需要判斷是否為檔案,然後把檔案引入進來即可。
在框架中PHP型別的配置檔案都是陣列形式的,所以在Php.php檔案中parse方法直接返回config屬性即可。
開始開心的測試吧!之前在env的檔案中配置了CONFIG_EXT這個值為yaml。
也就是說讀取config目錄下的配置檔案時,只能讀取擴充套件為yaml型別的檔案。
相關推薦
面試官:聊一下對框架配置載入的理解吧!
❝ 在上期聊了ThinkPHP類的自動載入,如你還不太瞭解可以跟這下文連結去進行檢視。本文會帶你一起解讀ThinkPHP配置檔案。 ❞ 前言 想了很久終於要開始系列文章的編寫了,期望是寫出提升和麵試都可以搞定的系列文章。 當你看到本文時,如果你發現咔咔沒有編寫到的面試熱點問題或者技術難點,期待評論區指出,一起
面試官:說說你對css效率的理解
大家好,我是小雨小雨,致力於分享有趣的、實用的技術文章。 內容分為翻譯和原創,如果有問題,歡迎隨時評論或私信,希望和大家一起進步。 大家的支援是我創作的動力。 選擇器的優先順序 眾所周知,選擇器是有權重的,優先順序從低到高,如下所示: 型別選擇器(例如,h1)和偽元素(例如,::before) 類選擇器
面試官:談一下你對DDD的理解?我:馬什麼梅?
領域模型(domain model)是對領域內的概念類或現實世界中物件的視覺化表示。領域模型也稱為概念模型、領域物件模型和分析物件模型。 ——《UML和模式應用》 我們在日常開發中,經常針對一些功能點爭論“這個功能不應該我改,應該是你那邊改”,最終被妥協改了之後都改不明白為什麼這個功能要在自己這邊改。區別於傳
面試官:說一下你常用的加密演算法
加密演算法我們整體可以分為:可逆加密和不可逆加密,可逆加密又可以分為:對稱加密和非對稱加密。 ## 一、不可逆加密 常見的不可逆加密演算法有`MD5`,`HMAC`,`SHA1`、`SHA-224`、`SHA-256`、`SHA-384`,和`SHA-512`,其中`SHA-224`、`SHA-256`、
面試官:這簡歷一看就是包裝過了!
在網際網路極速膨脹的社會背景下,各行各業湧入網際網路的IT民工日益增大。 早在2016年,我司釋出了Java、Ios工程師的招聘資訊,就Java工程師單個崗位而言,日收簡歷近200份,Ios日收簡歷近一千份。 沒錯,這就是當年培訓機構對Ios工程師這個崗位發起的市場討伐。而隨著近幾
面試官:兄弟,說說Java的static關鍵字吧
讀者乙在上一篇我去系列文章裡留言說,“我盲猜下一篇標題是,‘我去,你竟然不知道 static 關鍵字’”。我只能說乙猜對了一半,像我這麼有才華的博主,怎麼可能被讀者猜中了心思呢,必須搞點不一樣的啊,所以本篇文章的標題你看到了。 七年前,我從美女很多的蘇州回到美女也不少的洛陽,抱著一幅“從二線城市退居三線城
面試官:要不簡單聊一下你對MySQL索引的理解?
MySQL索引?這玩意兒還能簡單聊?明顯是在挖坑,幸好老夫早有準備,切聽我一一道來。 一、索引是什麼? 索引是幫
怎麼回答面試官:你對Spring的理解
spring呢,是pivotal公司維護的一系列開源工具的總稱,最為人所知的是spring mvc,事實上,他們都是基於spring framework,並且再其上繼續增強,為某一方面服務的java元件。最近spring framework 剛升級到5,非常不錯。比較常見的有
當面試官問:‘’談一下你面向物件的理解‘’時,你該如何回答~~~
回答面試一定要有深度,讓面試的大哥感覺你的水平有層次感面向物件程式設計,即OOP,是一種程式設計正規化,滿足面向物件程式設計的語言,一般會提供類、封裝、繼承等語法和概念來輔助我們來進行面向物件程式設計。型別被設計為將資料和行為捆綁在一起的東西,資料和行為被稱為型別的成員。我們
面試官:給我說一下你項目中的單點登錄是如何實現的?
分享圖片 .get 監聽 rec 返回 例子 比對 .exe 功能 一、單系統登錄機制 1、http無狀態協議 web應用采用browser/server架構,http作為通信協議。http是無狀態協議,瀏覽器的每一次請求,服務器會獨立處理,不與之前或之後的請求產生關聯,這
面試官:請說一下物件鎖和類鎖的區別
有鎖才有自由 生活中不存在絕對的自由,絕對的自由通常對應的無序和混沌,只有在道德、法律、倫理的約束下的相對自由,才能使人感受到自由。 而在多執行緒程式設計中,鎖是至關重要的,鎖就是道德,就是法律約束,沒有鎖的多執行緒環境將會是混亂的,所有執行緒都在爭奪資源,最後的結果就是導致系統崩潰,而有了鎖之後,多執行緒環
面試系列-面試官:你能給我解釋一下javascript中的this嗎?
一.前言 關於javascript中的this物件,可能已經被大家說爛了。 即使是這樣,我依然決定將這篇文章給水出來。畢竟全國在新型肺炎的影響下,公司沒法正常復工。 除了刷刷手機,還是要適當的學習一下。 廢柴是真不好當,勞逸結合才是王道。 二.正戲開始 面試官:你能給我解釋一下javasc
面試官:能解釋一下javascript中bind、apply和call這三個函式的用法嗎
一.前言 不知道大家還記不記得前一篇文章:《面試官:能解釋一下javascript中的this嗎》 那今天這篇文章雖然是介紹javascript中bind、apply和call函式,但是多少也和this有點關聯。 假如在前面那場面試末尾,面試官不依不饒繼續問你javascr
面試官:你剛說你喜歡研究新技術,那麼請說說你對 Blazor 的瞭解
閱讀本文大概需要 1.5 分鐘。 最近在幾個微信 .NET 交流群裡大家討論比較頻繁的話題就是這幾天自己的面試經歷。 面試官:“你剛說你喜歡研究新技術,那麼你對 Blazor 瞭解多少?”。 作為一位專注於 .NET 開發的軟體工程師,你好意思說你對 Blazor 一點也不解嗎?.NET 新技術也就是那
面試官:如果讓你寫個分散式配置中心,就問你慌不慌
## 前言 一位讀者朋友跟我反饋,能不能寫一篇比較全的配置中心的文章。自己最近在面試過程中有被面試官問:**如何設計一個配置中心?** 這個話題,由於自己在工作中也沒實際使用過配置中心,所以對於如何去設計是完全沒有概念的。 今天就給大家寫一篇去配置中心需要考慮的點,我也不是什麼配置中心開源專案的參與者,所
面試官:請講一下Redis主從複製的功能及實現原理
摘要:Redis在主從模式下會有許多問題需要考慮,這裡寫了一些關於redis在多伺服器下的一些問題分析和總結。 Redis單節點存在單點故障問題,為了解決單點問題,一般都需要對redis配置從節點,然後使用哨兵來監聽主節點的存活狀態,如果主節點掛掉,從節點能繼續提供快取功能。主從配置結合哨兵模式能解決單點故障
面試官:分散式事務講下 程式設計師:不清楚 然後結果就涼涼了
java、後端開發、程式設計師、分散式事務 分散式事務應該是面試官最喜歡問的題目之一 我對分散式事務的基本思路整理總結了一下,其實還有很多細節沒研究。 基礎知識準備 資料庫事務、分散式、微服務、分庫分表 資料庫事務的特性:原子性(Atomicity )、一致性( Cons
面試官:快排會寫嗎?
快排可以說是一道必知的常見面試題,同時也有多種實現方式。在這篇文章中,我使用的是隨機三路快排。 之所以使用隨機快速排序而不是普通的快排。是因為前者可以使得數列有序的概率降低,從而使隨機快速排序平均速度是比快速排序要快的。具體的兩者的效能差別可以看下這篇文章: blog.csdn.net/haelang/a
面試官:說說快速失敗和安全失敗是什麼
什麼是快速失敗(fail-fast)和安全失敗(fail-safe)?它們又和什麼內容有關係。以上兩點就是這篇文章的內容,廢話不多話,正文請慢用。 我們都接觸 HashMap、ArrayList 這些集合類,這些在 java.util 包的集合類就都是快速失敗的;而 java.util.concurrent
面試:談談你對大資料的理解
大資料概念: 大資料(big data):指無法在一定時間範圍內用常規軟體工具進行捕捉、管理和處理的資料集合, 是需要新處理模式才能具有更強的決策力、洞察發現力和流程優化能力的海量、高增長率和多樣化的資訊資產。 主要解決:海量資料的儲存和海量資料的分析計算問題。 大資料的