摘要:如果遍歷后沒有找到,則加載失敗。在之后碰到了之后直接拿來用,提高系統(tǒng)自動加載的性能。這里我們就講完了注冊自動加載。使用自動加載我們在中定義了我們自動加載函數(shù)式方法。
繼 生命周期的第二篇,大家盡可放心,不會隨便鴿文章的
第一篇中,我們提到了入口腳本,也說了,里面注冊了自動加載的功能
本文默認(rèn)你有自動加載和命名空間的基礎(chǔ)。如果沒有請 看此篇文章 php 類的自動加載與命名空間
自動加載機制php 的自動加載是 Loader 類中實現(xiàn)的,這個類在 base.php 中被引入
//base .php // 載入Loader類 require __DIR__ . "/library/think/Loader.php"; // 注冊自動加載 Loader::register();
我們程序在這里執(zhí)行了 Loader 中靜態(tài)方法 ,同時這也是一個全部的類register() 我們進(jìn)入 Loader.php ,按照上面執(zhí)行順序看看其核心是什么?
register()方法執(zhí)行流程 注冊系統(tǒng)自動加載此方法行數(shù)過長,我們一點一點來分析
// 注冊系統(tǒng)自動加載 spl_autoload_register($autoload ?: "thinkLoader::autoload", true, true);
這就是注冊我們的自動加載函數(shù),$autoload 這個變量是傳的參數(shù),考慮到你可以自己實現(xiàn)自己的加載類,為了方便拓展,TP可以讓你自己實現(xiàn)自己的類加載方法。
如果不了解這個函數(shù)的同學(xué),請看文章最頂部的那個連接,上面有詳細(xì)講解。
Composer自動加載支持$rootPath = self::getRootPath(); self::$composerPath = $rootPath . "vendor" . DIRECTORY_SEPARATOR . "composer" . DIRECTORY_SEPARATOR; // Composer自動加載支持 if (is_dir(self::$composerPath)) { if (is_file(self::$composerPath . "autoload_static.php")) { require self::$composerPath . "autoload_static.php"; // 獲取當(dāng)前加載的所有類 $declaredClass = get_declared_classes(); $composerClass = array_pop($declaredClass); foreach (["prefixLengthsPsr4", "prefixDirsPsr4", "fallbackDirsPsr4", "prefixesPsr0", "fallbackDirsPsr0", "classMap", "files"] as $attr) { if (property_exists($composerClass, $attr)) { self::${$attr} = $composerClass::${$attr}; } } } else { self::registerComposerLoader(self::$composerPath); } }
為了支持 composer 拓展,在自動注冊時候,把composer 也順帶一起注冊了,方便對拓展的調(diào)用。
autoload_static.php中的變量加載進(jìn)內(nèi)存中有一個難題:由于autoload_static.php 文件中的類名一直在變化,我們無法得到固定的類名。(如我系統(tǒng)中 類名為 ComposerStaticInit5109814b18095308ffe89ba7a1be18df)
為了把 require self::$composerPath . "autoload_static.php"; 中 的屬性 載入進(jìn)程序中,在這里我們換了一種形式
首先,獲取程序中加載的所有類名,然后取我們最后一個加載的類名(即數(shù)組中的最后一個)。
$declaredClass = get_declared_classes(); $composerClass = array_pop($declaredClass);
拿到了我們的類名,調(diào)用 property_exists($composerClass, $attr)檢查類中是否存在指定的屬性
疑問: composer_static 的參數(shù)代表是什么?foreach (["prefixLengthsPsr4", "prefixDirsPsr4", "fallbackDirsPsr4", "prefixesPsr0", "fallbackDirsPsr0", "classMap", "files"] as $attr) 中后面 ("fallbackDirsPsr4", "prefixesPsr0", "fallbackDirsPsr0", "classMap", "files")的作用是什么?
public static $classMap = array ( "AppHttpControllersAuthForgotPasswordController" => __DIR__ . "/../.." . "/app/Http/Controllers/Auth/ForgotPasswordController.php", "AppHttpControllersAuthLoginController" => __DIR__ . "/../.." . "/app/Http/Controllers/Auth/LoginController.php", "AppHttpControllersAuthRegisterController" => __DIR__ . "/../.." , …… )
直接命名空間全名與目錄的映射,簡單粗暴,也導(dǎo)致這個數(shù)組相當(dāng)?shù)拇蟆?/p>
public static $prefixLengthsPsr4 = array( "p" => array ( "phpDocumentorReflection" => 25, ), "S" => array ( "SymfonyPolyfillMbstring" => 26, "SymfonyComponentYaml" => 23, "SymfonyComponentVarDumper" => 28, ... ), ...); public static $prefixDirsPsr4 = array ( "phpDocumentorReflection" => array ( 0 => __DIR__ . "/.." . "/phpdocumentor/reflection-common/src", 1 => __DIR__ . "/.." . "/phpdocumentor/type-resolver/src", 2 => __DIR__ . "/.." . "/phpdocumentor/reflection-docblock/src", ), "SymfonyPolyfillMbstring" => array ( 0 => __DIR__ . "/.." . "/symfony/polyfill-mbstring", ), "SymfonyComponentYaml" => array ( 0 => __DIR__ . "/.." . "/symfony/yaml", ), ...)
PSR4 標(biāo)準(zhǔn)頂級命名空間映射用了兩個數(shù)組,第一個是用命名空間第一個字母作為前綴索引,然后是 頂級命名空間,但是最終并不是文件路徑,而是 頂級命名空間的長度。為什么呢?
因為 PSR4 標(biāo)準(zhǔn)是用頂級命名空間目錄替換頂級命名空間,所以獲得頂級命名空間的長度很重要。
具體說明這些數(shù)組的作用:
假如我們找 SymfonyPolyfillMbstringexample 這個命名空間,通過前綴索引和字符串匹配我們得到了
"SymfonyPolyfillMbstring" => 26,
這條記錄,鍵是頂級命名空間,值是命名空間的長度。拿到頂級命名空間后去 $prefixDirsPsr4數(shù)組 獲取它的映射目錄數(shù)組:(注意映射目錄可能不止一條)
array ( 0 => __DIR__ . "/.." . "/symfony/polyfill-mbstring", )
然后我們就可以將命名空間 SymfonyPolyfillMbstringexample 前26個字符替換成目錄 __DIR__ . "/.." . "/symfony/polyfill-mbstring ,我們就得到了__DIR__ . "/.." . "/symfony/polyfill-mbstring/example.php,先驗證磁盤上這個文件是否存在,如果不存在接著遍歷。如果遍歷后沒有找到,則加載失敗。
注: 其實作為一個web框架,composer里面的東西,不應(yīng)該由ThinkPHP關(guān)心的,但由于 TP5 自己原生的框架包 的設(shè)計沒有完全包容 composer, 所在注冊自動加載的時候會拿去其屬性值自己來使用(僅限自己理解,如果與您觀點不同歡迎討論)
注冊命名空間定義// 注冊命名空間定義 self::addNamespace([ "think" => __DIR__, "traits" => dirname(__DIR__) . DIRECTORY_SEPARATOR . "traits", ]); // 加載類庫映射文件 if (is_file($rootPath . "runtime" . DIRECTORY_SEPARATOR . "classmap.php")) { self::addClassMap(__include_file($rootPath . "runtime" . DIRECTORY_SEPARATOR . "classmap.php")); } // 自動加載extend目錄 self::addAutoLoadDir($rootPath . "extend");
這后面的代碼都大同小異,都是把 所需要用到的類,映射到Psr4空間這個靜態(tài)變量中。到時候方便我們使用命名空間進(jìn)行調(diào)用。
// 加載類庫映射文件 if (is_file($rootPath . "runtime" . DIRECTORY_SEPARATOR . "classmap.php")) { self::addClassMap(__include_file($rootPath . "runtime" . DIRECTORY_SEPARATOR . "classmap.php")); }
在 TP5 代碼下執(zhí)行php think optimize:autoload 就會在runtime下生成 classmap.php 文件,文件形式
return [ "appindexcontrollerIndex" => "D:/app/tp5/application/" . "index/controller/Index.php", "thinkApp" => "D:/app/tp5/thinkphp/library/" . "/think/App.php", "thinkBuild" => "D:/app/tp5/thinkphp/library/" . "/think/Build.php", "thinkCache" => "D:/app/tp5/thinkphp/library/" . "/think/Cache.php", "thinkCollection" => "D:/app/tp5/thinkphp/library/" . "/think/Collection.php", ... ]
生成類庫映射文件,會在runtime目錄下面生成classmap.php文件,生成的類庫映射文件會掃描系統(tǒng)目錄和應(yīng)用目錄的類庫。在之后碰到了之后直接拿來用,提高系統(tǒng)自動加載的性能。
register() 函數(shù)這里就大概分析結(jié)束了。 這里我們就講完了 注冊自動加載。
使用自動加載我們在 register 中定義了我們自動加載函數(shù)式 Loader::autoload()方法。 我們就小試牛刀,在我們的 base.php 中,我們加載完 自動加載機制后,就會加載我們的異常處理
// 載入Loader類 require __DIR__ . "/library/think/Loader.php"; // 注冊自動加載 Loader::register(); // 注冊錯誤和異常處理機制 Error::register();
在這時的狀態(tài)里 Error 不存在,所有會進(jìn)入我們的自動加載方法中重新試一下。
//函數(shù)整體內(nèi)容 public static function autoload($class) { if (isset(self::$classAlias[$class])) { return class_alias(self::$classAlias[$class], $class); } if ($file = self::findFile($class)) { // Win環(huán)境嚴(yán)格區(qū)分大小寫 if (strpos(PHP_OS, "WIN") !== false && pathinfo($file, PATHINFO_FILENAME) != pathinfo(realpath($file), PATHINFO_FILENAME)) { return false; } __include_file($file); return true; } }
我們截取片段一點一點分析。
if (isset(self::$classAlias[$class])) { return class_alias(self::$classAlias[$class], $class); }
這一段是判斷我們我們是否對該類設(shè)置別名,但明顯我們此時還沒有設(shè)置。
if ($file = self::findFile($class)) { // Win環(huán)境嚴(yán)格區(qū)分大小寫 if (strpos(PHP_OS, "WIN") !== false && pathinfo($file, PATHINFO_FILENAME) != pathinfo(realpath($file), PATHINFO_FILENAME)) { return false; } __include_file($file); return true; }
findFile($class) 如果我們之前緩存了 classMap 在runtime文件夾下,那么他會直接返回。(這也就是為什么我們緩存 classMap 會提升性能的原因),如果沒有緩存就配合我們之前存儲映射關(guān)系的靜態(tài)數(shù)組prefixDirsPsr4,和 prefixLengthsPsr4來找尋文件的目錄,速度會相對慢很多。 如果沒有找到那么就返回空, spl_autoload_register 會判斷沒有找到該類,拋出錯誤。
如果找到就消除 linux 和 window 對路徑名稱的差異。(linux 嚴(yán)格區(qū)分大小寫,而win 沒有嚴(yán)格區(qū)分)
這里主要是擔(dān)心在window環(huán)境下,路徑名稱大小寫沒分,所以我們根據(jù)linux的目錄規(guī)則重寫了文件路徑
之后再加我們的目錄文件
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/31572.html
摘要:本文是作者自己對中線程的狀態(tài)線程間協(xié)作相關(guān)使用的理解與總結(jié),不對之處,望指出,共勉。當(dāng)中的的數(shù)目而不是已占用的位置數(shù)大于集合番一文通版集合番一文通版垃圾回收機制講得很透徹,深入淺出。 一小時搞明白自定義注解 Annotation(注解)就是 Java 提供了一種元程序中的元素關(guān)聯(lián)任何信息和著任何元數(shù)據(jù)(metadata)的途徑和方法。Annotion(注解) 是一個接口,程序可以通過...
摘要:注意,這就與普通的腳本引用加載立即執(zhí)行完全不同了接下來,就輪到微信小程序的函數(shù)出場了。所以深入理解微信小程序的模塊化機制也是很有價值的 (注: 本文中所列微信小程序工具代碼,并非為微信小程序原始代碼,而是學(xué)習(xí)歸納的示意代碼) 在學(xué)習(xí)開發(fā)微信小程序中, 分析總結(jié)了最近版本微信小程序模塊化的函數(shù) require的加載與初始化模塊機制,歸納說來,小程序JS模塊加載可分為兩大步驟:一,JS模塊...
摘要:接下來我看看一下函數(shù)我們先按照分支走為讀取是里的對象,饒了這大的一個圈子,那么接下來一起來看一看對你的輸入配置做了怎么樣的處理吧 打開webpeck-cli下的convert-argv.js文件 // 定義options為空數(shù)組 const options = []; // webpack -d 檢查 -d指令 if (argv.d) { //... } ...
摘要:模塊和將下面的渲染機制,安全機制,插件機制等等隱藏起來,提供一個接口層。進(jìn)行網(wǎng)頁的渲染進(jìn)程,可能有多個。最后進(jìn)程將結(jié)果由線程傳遞給進(jìn)程最后,進(jìn)程接收到結(jié)果并將結(jié)果繪制出來。 這是之前在簡書上面的處女作,也搬過來了,以后就一直在 segmentfault 上面寫文章了,webkit技術(shù)內(nèi)幕-朱永盛是我大四買的書,很舊的一本書了,當(dāng)時只看了一點點,一直沒繼續(xù)看完它,現(xiàn)在才看完,,,說來慚愧...
摘要:數(shù)據(jù)源頻繁更新的場景,如彈幕等的優(yōu)勢會非常明顯進(jìn)一步來講,結(jié)論是列表頁展示界面,需要支持動畫,或者頻繁更新,局部刷新,建議使用,更加強大完善,易擴展其它情況如微信卡包列表頁兩者都,但在使用上會更加方便,快捷。 本文來自于騰訊bugly開發(fā)者社區(qū),非經(jīng)作者同意,請勿轉(zhuǎn)載,原文地址:http://dev.qq.com/topic/5811d... 作者:黃寧源 一,背景 RecyclerV...
閱讀 1988·2021-11-19 09:40
閱讀 1931·2021-09-28 09:36
閱讀 2279·2021-09-22 10:02
閱讀 2724·2019-08-30 14:00
閱讀 1948·2019-08-29 15:31
閱讀 2893·2019-08-29 15:11
閱讀 2905·2019-08-29 13:04
閱讀 1080·2019-08-27 10:55