如題,今天感覺(jué)好久沒(méi)有更新博客了。最近迷上了物聯(lián)網(wǎng)開(kāi)發(fā)。一直在研究stm32、51這些東西。想起來(lái)前幾天群里面有人問(wèn)到tp擴(kuò)展包原理。其實(shí)這個(gè)前幾年也就研究過(guò)。網(wǎng)上搜了搜發(fā)現(xiàn)相關(guān)文章也很少(也有可能是我搜索姿勢(shì)不對(duì))今天就來(lái)寫(xiě)一篇thinkphp composer包加載原理
概覽當(dāng)進(jìn)行composer update或者 composer require操作時(shí)。則會(huì)執(zhí)行service:discover這個(gè)命令。把當(dāng)前所有已經(jīng)加載的庫(kù)信息都進(jìn)行一次匹配。如果匹配到了think關(guān)鍵字的services屬性。則把服務(wù)類輸出成配置文件到vendor/services.php文件中當(dāng)一次應(yīng)用初始化(通常為一次訪問(wèn)開(kāi)始時(shí)).則會(huì)引入vendor/services.php中的service服務(wù)類到當(dāng)前應(yīng)用內(nèi)進(jìn)行初始化源碼解析composer包加載流程文字詳解 建議先閱讀一下這篇前兩年我寫(xiě)的文章 Thinkphp6源碼解析之分析 路由篇-請(qǐng)求流程在第三步進(jìn)入到Http->runWithRequest這個(gè)方法中后。可以看到又調(diào)用了initialize方法
追進(jìn)這個(gè)方法可以看到
(資料圖片)
追進(jìn)initialize方法看實(shí)現(xiàn)
/** * 初始化應(yīng)用 * @access public * @return $this */ public function initialize() { // 設(shè)置當(dāng)前初始化狀態(tài) $this->initialized = true; // 設(shè)置應(yīng)用開(kāi)始時(shí)間 $this->beginTime = microtime(true); // 獲取到php的內(nèi)存 $this->beginMem = memory_get_usage(); // 加載環(huán)境變量 例如當(dāng)前應(yīng)用目錄下的 .env文件 $this->loadEnv($this->envName); // 設(shè)置配置文件后綴 $this->configExt = $this->env->get("config_ext", ".php"); // 調(diào)試模式設(shè)置 $this->debugModeInit(); // 加載全局初始化文件 $this->load(); // 加載應(yīng)用默認(rèn)語(yǔ)言包 $this->loadLangPack(); // 監(jiān)聽(tīng)AppInit $this->event->trigger(AppInit::class); // 設(shè)置php默認(rèn)時(shí)區(qū) date_default_timezone_set($this->config->get("app.default_timezone", "Asia/Shanghai")); // 初始化當(dāng)前系統(tǒng)配置的默認(rèn)服務(wù) foreach ($this->initializers as $initializer) {// 調(diào)用make函數(shù)生成對(duì)象。并且執(zhí)行對(duì)象中的init方法 $this->make($initializer)->init($this); } return $this; }重點(diǎn)是初始化當(dāng)前系統(tǒng)配置的默認(rèn)服務(wù)這個(gè)$this->make($initializer)->init($this)函數(shù),看看initializers屬性
/** * 應(yīng)用初始化器 * @var array */ protected $initializers = [ Error::class, RegisterService::class, BootService::class, ];追到這里就是關(guān)鍵了。上面把這里面的類進(jìn)行初始化。并且執(zhí)行類中的init方法。直接看RegisterService::class類的init方法
public function init(App $app) { // 獲取當(dāng)前項(xiàng)目根目錄。拼接上 vendor/services.php $file = $app->getRootPath() . "vendor/services.php"; $services = $this->services; if (is_file($file)) { $services = array_merge($services, include $file); } // 初始化services foreach ($services as $service) { if (class_exists($service)) { $app->register($service); } } }讀到這里的可以看看自己項(xiàng)目vendor目錄下是不是有一個(gè)services.php,接下來(lái)講一講composer.json這個(gè)文件在tp框架中的composer.json有這樣一個(gè)配置
這里這個(gè)概念我直接讓chatgpt來(lái)解讀。解讀內(nèi)容如下
接下來(lái)直接看service:discover這個(gè)命令。追到vendor\topthink\framework\src\think\console\command\ServiceDiscover.php文件
public function execute(Input $input, Output $output) { // 獲取到當(dāng)前項(xiàng)目根目錄下的 vendor/composer/installed.json 文件 if (is_file($path = $this->app->getRootPath() . "vendor/composer/installed.json")) { // json解析 $packages = json_decode(@file_get_contents($path), true); // Compatibility with Composer 2.0 if (isset($packages["packages"])) { $packages = $packages["packages"]; } $services = []; foreach ($packages as $package) { // 判斷當(dāng)前包是否在extra字段里面聲明了think關(guān)鍵字中的services屬性。如果聲明了就把services給裝載到services變量?jī)?nèi) if (!empty($package["extra"]["think"]["services"])) { $services = array_merge($services, (array) $package["extra"]["think"]["services"]); } } $header = "http:// This file is automatically generated at:" . date("Y-m-d H:i:s") . PHP_EOL . "declare (strict_types = 1);" . PHP_EOL; // 用var_export函數(shù)把services變量打印成可讀性代碼。并且寫(xiě)入到根目錄vendor目錄下的services $content = "app->getRootPath() . "vendor/services.php", $content); $output->writeln("Succeed! "); }一直到這就算結(jié)束了
寫(xiě)在最后如果覺(jué)得這篇文章對(duì)你有幫助。不妨點(diǎn)個(gè)贊留個(gè)關(guān)注再走
標(biāo)簽:
Copyright @ 2001-2013 m.caidouzi.com All Rights Reserved 財(cái)經(jīng)新聞網(wǎng) 版權(quán)所有 京ICP備12018864號(hào)-1
網(wǎng)站所登新聞、資訊等內(nèi)容, 均為相關(guān)單位具有著作權(quán),轉(zhuǎn)載請(qǐng)注明出處
未經(jīng)彩迅新聞網(wǎng)書(shū)面授權(quán),請(qǐng)勿建立鏡像 聯(lián)系我們: 291 32 36@qq.com