* 初始化應(yīng)用或模塊
* @access public
* @param string $module 模塊名
* @return void
*/
public function init($module = '')
{
// 定位模塊目錄
$module = $module ? $module . DIRECTORY_SEPARATOR : '';
/**
* 第一次:D:\\\\phpstudy_pro\\\\WWW\\\\ThinkPHPSourceCodeAnalysis\\\\application\\\\
* 第二次:D:\\\\phpstudy_pro\\\\WWW\\\\ThinkPHPSourceCodeAnalysis\\\\application\\\\index\\\\
*/
$path = $this->appPath . $module;
// 加載初始化文件
if (is_file($path . 'init.php')) {
include $path . 'init.php';
} elseif (is_file($this->runtimePath . $module . 'init.php')) {
include $this->runtimePath . $module . 'init.php';
} else {
// 加載行為擴展文件
if (is_file($path . 'tags.php')) {
$tags = include $path . 'tags.php';
if (is_array($tags)) {
$this->hook->import($tags);
}
}
// 加載公共文件
if (is_file($path . 'common.php')) {
include_once $path . 'common.php';
}
if ('' == $module) {
// 加載系統(tǒng)助手函數(shù)
include $this->thinkPath . 'helper.php';
}
// 加載中間件
if (is_file($path . 'middleware.php')) {
$middleware = include $path . 'middleware.php';
if (is_array($middleware)) {
$this->middleware->import($middleware);
}
}
// 注冊服務(wù)的容器對象實例
if (is_file($path . 'provider.php')) {
$provider = include $path . 'provider.php';
if (is_array($provider)) {
$this->bindTo($provider);
}
}
/**
* $path : "D:\\\\phpstudy_pro\\\\WWW\\\\ThinkPHPSourceCodeAnalysis\\\\application\\\\"
* "D:\\\\phpstudy_pro\\\\WWW\\\\ThinkPHPSourceCodeAnalysis\\\\application\\\\index\\\\"
*/
// 自動讀取配置文件
if (is_dir($path . 'config')) {
$dir = $path . 'config' . DIRECTORY_SEPARATOR;
} elseif (is_dir($this->configPath . $module)) {
// D:\\\\phpstudy_pro\\\\WWW\\\\ThinkPHPSourceCodeAnalysis\\\\config\\\\
$dir = $this->configPath . $module;
}
// scandir:以升序的方式讀取目錄中的文件
// 返回就是config目錄中的所有文件
$files = isset($dir) ? scandir($dir) : [];
foreach ($files as $file) {
/**
* $this->configExt:配置文件的后綴
* pathinfo返回的是文件后綴,關(guān)于pathinfo共有三個可選的參數(shù)PATHINFO_DIRNAME、PATHINFO_BASENAME、PATHINFO_EXTENSION,分別為只返回文件名,文件目錄名,文件擴展
*/
if ('.' . pathinfo($file, PATHINFO_EXTENSION) === $this->configExt) {
/**
* 倆個參數(shù)分別為
* 1.目錄 config目錄下的文件
* 2.config目錄下文件名
*/
$this->config->load($dir . $file, pathinfo($file, PATHINFO_FILENAME));
}
}
}
$this->setModulePath($path);
if ($module) {
// 對容器中的對象實例進行配置更新
$this->containerConfigUpdate($module);
}
}
這里附帶上一份代碼,可以對著代碼看上邊的執(zhí)行流程,對每一步都做了簡單的說明。
咔咔個人見解對源碼進行優(yōu)化
在設(shè)置模塊的這步代碼咔咔感覺不是很是嚴謹,因為init方法會在倆個地方進行執(zhí)行。
第一次的模塊為空,這塊代碼執(zhí)行是沒有任何意義的。
下面在對容器的對象實例進行配置更新時進行了一次判斷,判斷模塊的這個參數(shù)是否為空,如果不為空才會執(zhí)行。
那么同樣的道理,咔咔感覺在設(shè)置模塊路徑這塊也應(yīng)該在這個判斷里邊。
雖說第二次執(zhí)行會把第一次的結(jié)果覆蓋掉,但是咔咔感覺下圖這樣使用才會更好。
四、對容器中的對象實例進行更新配置
在上一節(jié)中這里就是最后的內(nèi)容,那這個對實例進行更新配置,到底更新了什么,怎么更新沒有說明。
在這一小節(jié)中就會做出說明,同樣可以配合著前言的思維導圖看。
在這一節(jié)中咔咔感覺最重要的就是下圖的內(nèi)容了。
我們可以隨意追蹤一到倆個方法查看一下那邊到底執(zhí)行了什么方法。
追蹤方法Db::init()
追蹤方法過來后可以看到就是對Db類中的config屬性進行賦值,把database中的值賦值給Db類中的config屬性。
追蹤方法$this->middleware->setConfig()
來到中間件這個類里邊,可以看到就是把本類的配置和傳遞過來的參數(shù)類進行合并,同樣也是進行config屬性的賦值。
跟上邊案例的Db類的init方法實現(xiàn)的效果是一致的。
這里在提一嘴就是在對容器中的對象實例進行更新配置這一幅圖中可以看到紫色部分是在本類中沒有引用的。
那么這是怎么可以進行執(zhí)行的呢!是因為App類繼承了容器類,容器類中有四個魔術(shù)方法,其中有一個__get方法,就是在獲取不存在的屬性時會執(zhí)行那個方法。
在魔術(shù)方法__get方法中執(zhí)行了一個make方法,這個make方法說了好多次了,這個方法最終會返回一個應(yīng)用的實例,然后用這個實例調(diào)用對應(yīng)實例類的方法。
這一塊一定要理解好,閱讀源碼就是這個樣子,我們需要對一切未知的進行的解決,只有這樣才能提高我們的編程能力和思想。
五、淺談?wù){(diào)試模式以及代碼冗余
本節(jié)會對調(diào)試模式做出簡單的說明,并且會對框架代碼冗余情況進行簡單的提出。
沒有人寫的代碼是沒有漏洞的,如果有那就是你還沒有達到一定的造詣。
調(diào)試模式
在第一節(jié)中只提到了initialize方法的上半部分,因為在這一節(jié)之前聊的都是關(guān)于應(yīng)用初始化init的內(nèi)容。
接下來會對這一塊的內(nèi)容進行簡單的說明。
接下來的內(nèi)容估計不是很好理解,都是平時在工作中根本使用不到的。
上邊這三個先暫時認識就行,后期如果有機會會專門出一篇文章做解釋的。
關(guān)于框架代碼冗余
這里也僅僅代表咔咔個人的觀點。
可以先看看這部分的代碼,這倆處代碼是不是很是熟悉,沒錯就是在上文的init方法中容器對象實例配置更新見到過。
如圖
這塊也就是咔咔個人提出的見解,由于咔咔式針對5.1做的源碼解讀,不太了解新版版是否做出了改動。
六、總結(jié)
本節(jié)主要是針對框架執(zhí)行流程中的初始化應(yīng)用做了簡單的探討。
至于在app類的run方法下面還有很多的執(zhí)行過程在這一節(jié)中沒有做過多的解釋。
在閱讀源碼的過程中給大家提了一個很好得小技巧,那就是如何去查看一個方法都在哪里進行了執(zhí)行。
這個方法為debug_backtrace,這個方法需要大家多使用幾次就知道怎么使用了,因為在打印出來的結(jié)果中也存在很多無用的信息。
這個方法在調(diào)試源碼的過程中是非常有效的,一定要好好利用這個方法。
在就是對初始化應(yīng)用init方法進行了特別詳細的介紹。
其中咔咔感覺這塊設(shè)計最好的就是在容器中的對象實例進行更新配置那一塊,先讀取所有的配置,然后在通過各個類的方法進行配置的設(shè)置。
這種代碼規(guī)劃和設(shè)計思路值得我們?nèi)W習。
最后聊到了調(diào)試模式和框架的代碼冗余問題,關(guān)于調(diào)試模式這里咔咔給大家提個醒項目在線上的調(diào)試模式一定要關(guān)閉。
否則你的項目就類似于裸奔的存在,沒有一點點的安全可言。
這塊有點不好理解的就是對于緩沖區(qū),關(guān)于這塊的內(nèi)容咔咔認為暫時沒有必要去鉆牛角尖,先認識認識然后在進行深入的研究。
緩沖區(qū)的這塊內(nèi)容估計工作了三四年的也很少有人使用,所以先認識,知道怎么一回事,咔咔后期學習了之后在給大家進行補充。
直到這里關(guān)于框架的執(zhí)行流程之初始化應(yīng)用就結(jié)束了,這一節(jié)沒有過深需要學習的,主要是其中的代碼設(shè)計模式和實現(xiàn)思路。
最后這個圖大家一定要跟著源碼看一看哈!
“
堅持學習、堅持寫博、堅持分享是咔咔從業(yè)以來一直所秉持的信念。希望在偌大互聯(lián)網(wǎng)中咔咔的文章能帶給你一絲絲幫助。我是咔咔,下期見。
”
更多關(guān)于云服務(wù)器,域名注冊,虛擬主機的問題,請訪問西部數(shù)碼官網(wǎng):m.ps-sw.cn