亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

ThinkPHP5.1 源碼淺析(二)自動(dòng)加載機(jī)制

mudiyouyou / 674人閱讀

摘要:如果遍歷后沒有找到,則加載失敗。在之后碰到了之后直接拿來用,提高系統(tǒng)自動(dòng)加載的性能。這里我們就講完了注冊(cè)自動(dòng)加載。使用自動(dòng)加載我們?cè)谥卸x了我們自動(dòng)加載函數(shù)式方法。

繼 生命周期的第二篇,大家盡可放心,不會(huì)隨便鴿文章的

第一篇中,我們提到了入口腳本,也說了,里面注冊(cè)了自動(dòng)加載的功能

本文默認(rèn)你有自動(dòng)加載和命名空間的基礎(chǔ)。如果沒有請(qǐng) 看此篇文章 php 類的自動(dòng)加載與命名空間

自動(dòng)加載機(jī)制

php 的自動(dòng)加載是 Loader 類中實(shí)現(xiàn)的,這個(gè)類在 base.php 中被引入

//base .php
// 載入Loader類
require __DIR__ . "/library/think/Loader.php";

// 注冊(cè)自動(dòng)加載
Loader::register();

我們程序在這里執(zhí)行了 Loader 中靜態(tài)方法 ,同時(shí)這也是一個(gè)全部的類register() 我們進(jìn)入 Loader.php ,按照上面執(zhí)行順序看看其核心是什么?

register()方法執(zhí)行流程

注冊(cè)系統(tǒng)自動(dòng)加載

此方法行數(shù)過長(zhǎng),我們一點(diǎn)一點(diǎn)來分析

// 注冊(cè)系統(tǒng)自動(dòng)加載
        spl_autoload_register($autoload ?: "thinkLoader::autoload", true, true);

這就是注冊(cè)我們的自動(dòng)加載函數(shù),$autoload 這個(gè)變量是傳的參數(shù),考慮到你可以自己實(shí)現(xiàn)自己的加載類,為了方便拓展,TP可以讓你自己實(shí)現(xiàn)自己的類加載方法。

如果不了解這個(gè)函數(shù)的同學(xué),請(qǐng)看文章最頂部的那個(gè)連接,上面有詳細(xì)講解。

Composer自動(dòng)加載支持
$rootPath = self::getRootPath();
        self::$composerPath = $rootPath . "vendor" . DIRECTORY_SEPARATOR . "composer" . DIRECTORY_SEPARATOR;

        // Composer自動(dòng)加載支持
        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 拓展,在自動(dòng)注冊(cè)時(shí)候,把composer 也順帶一起注冊(cè)了,方便對(duì)拓展的調(diào)用。

autoload_static.php中的變量加載進(jìn)內(nèi)存中有一個(gè)難題:由于autoload_static.php 文件中的類名一直在變化,我們無法得到固定的類名。(如我系統(tǒng)中 類名為 ComposerStaticInit5109814b18095308ffe89ba7a1be18df

為了把 require self::$composerPath . "autoload_static.php"; 中 的屬性 載入進(jìn)程序中,在這里我們換了一種形式

首先,獲取程序中加載的所有類名,然后取我們最后一個(gè)加載的類名(即數(shù)組中的最后一個(gè))。

$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")的作用是什么?
classMap(命名空間映射)
  public static $classMap = array (

      "AppHttpControllersAuthForgotPasswordController"
              => __DIR__ . "/../.." . "/app/Http/Controllers/Auth/ForgotPasswordController.php",

      "AppHttpControllersAuthLoginController"
              => __DIR__ . "/../.." . "/app/Http/Controllers/Auth/LoginController.php",

      "AppHttpControllersAuthRegisterController"
              => __DIR__ . "/../.." ,
              ……
)

直接命名空間全名與目錄的映射,簡(jiǎn)單粗暴,也導(dǎo)致這個(gè)數(shù)組相當(dāng)?shù)拇蟆?/p>

PSR4 標(biāo)準(zhǔn)頂級(jí)命名空間映射數(shù)組:
  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)頂級(jí)命名空間映射用了兩個(gè)數(shù)組,第一個(gè)是用命名空間第一個(gè)字母作為前綴索引,然后是 頂級(jí)命名空間,但是最終并不是文件路徑,而是 頂級(jí)命名空間的長(zhǎng)度。為什么呢?

因?yàn)?PSR4 標(biāo)準(zhǔn)是用頂級(jí)命名空間目錄替換頂級(jí)命名空間,所以獲得頂級(jí)命名空間的長(zhǎng)度很重要。

具體說明這些數(shù)組的作用:

假如我們找 SymfonyPolyfillMbstringexample 這個(gè)命名空間,通過前綴索引和字符串匹配我們得到了

"SymfonyPolyfillMbstring" => 26,

這條記錄,鍵是頂級(jí)命名空間,值是命名空間的長(zhǎng)度。拿到頂級(jí)命名空間后去 $prefixDirsPsr4數(shù)組 獲取它的映射目錄數(shù)組:(注意映射目錄可能不止一條)

 array (
              0 => __DIR__ . "/.." . "/symfony/polyfill-mbstring",
          )

然后我們就可以將命名空間 SymfonyPolyfillMbstringexample 前26個(gè)字符替換成目錄 __DIR__ . "/.." . "/symfony/polyfill-mbstring ,我們就得到了__DIR__ . "/.." . "/symfony/polyfill-mbstring/example.php,先驗(yàn)證磁盤上這個(gè)文件是否存在,如果不存在接著遍歷。如果遍歷后沒有找到,則加載失敗。

注: 其實(shí)作為一個(gè)web框架,composer里面的東西,不應(yīng)該由ThinkPHP關(guān)心的,但由于 TP5 自己原生的框架包 的設(shè)計(jì)沒有完全包容 composer, 所在注冊(cè)自動(dòng)加載的時(shí)候會(huì)拿去其屬性值自己來使用(僅限自己理解,如果與您觀點(diǎn)不同歡迎討論)

注冊(cè)命名空間定義
// 注冊(cè)命名空間定義
        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"));
        }

        // 自動(dòng)加載extend目錄
        self::addAutoLoadDir($rootPath . "extend");

這后面的代碼都大同小異,都是把 所需要用到的類,映射到Psr4空間這個(gè)靜態(tài)變量中。到時(shí)候方便我們使用命名空間進(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 就會(huì)在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",
    ...
    ]

生成類庫映射文件,會(huì)在runtime目錄下面生成classmap.php文件,生成的類庫映射文件會(huì)掃描系統(tǒng)目錄和應(yīng)用目錄的類庫。在之后碰到了之后直接拿來用,提高系統(tǒng)自動(dòng)加載的性能。

register() 函數(shù)這里就大概分析結(jié)束了。 這里我們就講完了 注冊(cè)自動(dòng)加載。

使用自動(dòng)加載

我們?cè)?register 中定義了我們自動(dòng)加載函數(shù)式 Loader::autoload()方法。 我們就小試牛刀,在我們的 base.php 中,我們加載完 自動(dòng)加載機(jī)制后,就會(huì)加載我們的異常處理

// 載入Loader類
require __DIR__ . "/library/think/Loader.php";

// 注冊(cè)自動(dòng)加載
Loader::register();

// 注冊(cè)錯(cuò)誤和異常處理機(jī)制
Error::register();

在這時(shí)的狀態(tài)里 Error 不存在,所有會(huì)進(jìn)入我們的自動(dòng)加載方法中重新試一下。

//函數(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;
        }
    }

我們截取片段一點(diǎn)一點(diǎn)分析。

if (isset(self::$classAlias[$class])) {
            return class_alias(self::$classAlias[$class], $class);
        }

這一段是判斷我們我們是否對(duì)該類設(shè)置別名,但明顯我們此時(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文件夾下,那么他會(huì)直接返回。(這也就是為什么我們緩存 classMap 會(huì)提升性能的原因),如果沒有緩存就配合我們之前存儲(chǔ)映射關(guān)系的靜態(tài)數(shù)組prefixDirsPsr4,和 prefixLengthsPsr4來找尋文件的目錄,速度會(huì)相對(duì)慢很多。 如果沒有找到那么就返回空, spl_autoload_register 會(huì)判斷沒有找到該類,拋出錯(cuò)誤。

如果找到就消除 linux 和 window 對(duì)路徑名稱的差異。(linux 嚴(yán)格區(qū)分大小寫,而win 沒有嚴(yán)格區(qū)分)

這里主要是擔(dān)心在window環(huán)境下,路徑名稱大小寫沒分,所以我們根據(jù)linux的目錄規(guī)則重寫了文件路徑

之后再加我們的目錄文件

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/31572.html

相關(guān)文章

  • Java相關(guān)

    摘要:本文是作者自己對(duì)中線程的狀態(tài)線程間協(xié)作相關(guān)使用的理解與總結(jié),不對(duì)之處,望指出,共勉。當(dāng)中的的數(shù)目而不是已占用的位置數(shù)大于集合番一文通版集合番一文通版垃圾回收機(jī)制講得很透徹,深入淺出。 一小時(shí)搞明白自定義注解 Annotation(注解)就是 Java 提供了一種元程序中的元素關(guān)聯(lián)任何信息和著任何元數(shù)據(jù)(metadata)的途徑和方法。Annotion(注解) 是一個(gè)接口,程序可以通過...

    wangtdgoodluck 評(píng)論0 收藏0
  • 微信小程序的require機(jī)制淺析

    摘要:注意,這就與普通的腳本引用加載立即執(zhí)行完全不同了接下來,就輪到微信小程序的函數(shù)出場(chǎng)了。所以深入理解微信小程序的模塊化機(jī)制也是很有價(jià)值的 (注: 本文中所列微信小程序工具代碼,并非為微信小程序原始代碼,而是學(xué)習(xí)歸納的示意代碼) 在學(xué)習(xí)開發(fā)微信小程序中, 分析總結(jié)了最近版本微信小程序模塊化的函數(shù) require的加載與初始化模塊機(jī)制,歸納說來,小程序JS模塊加載可分為兩大步驟:一,JS模塊...

    boredream 評(píng)論0 收藏0
  • 淺析webpack源碼之convert-argv模塊(

    摘要:接下來我看看一下函數(shù)我們先按照分支走為讀取是里的對(duì)象,饒了這大的一個(gè)圈子,那么接下來一起來看一看對(duì)你的輸入配置做了怎么樣的處理吧 打開webpeck-cli下的convert-argv.js文件 // 定義options為空數(shù)組 const options = []; // webpack -d 檢查 -d指令 if (argv.d) { //... } ...

    lemon 評(píng)論0 收藏0
  • webkit渲染機(jī)制淺析

    摘要:模塊和將下面的渲染機(jī)制,安全機(jī)制,插件機(jī)制等等隱藏起來,提供一個(gè)接口層。進(jìn)行網(wǎng)頁的渲染進(jìn)程,可能有多個(gè)。最后進(jìn)程將結(jié)果由線程傳遞給進(jìn)程最后,進(jìn)程接收到結(jié)果并將結(jié)果繪制出來。 這是之前在簡(jiǎn)書上面的處女作,也搬過來了,以后就一直在 segmentfault 上面寫文章了,webkit技術(shù)內(nèi)幕-朱永盛是我大四買的書,很舊的一本書了,當(dāng)時(shí)只看了一點(diǎn)點(diǎn),一直沒繼續(xù)看完它,現(xiàn)在才看完,,,說來慚愧...

    Cobub 評(píng)論0 收藏0
  • 【騰訊Bugly干貨分享】Android ListView與RecyclerView對(duì)比淺析--緩存

    摘要:數(shù)據(jù)源頻繁更新的場(chǎng)景,如彈幕等的優(yōu)勢(shì)會(huì)非常明顯進(jìn)一步來講,結(jié)論是列表頁展示界面,需要支持動(dòng)畫,或者頻繁更新,局部刷新,建議使用,更加強(qiáng)大完善,易擴(kuò)展其它情況如微信卡包列表頁兩者都,但在使用上會(huì)更加方便,快捷。 本文來自于騰訊bugly開發(fā)者社區(qū),非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載,原文地址:http://dev.qq.com/topic/5811d... 作者:黃寧源 一,背景 RecyclerV...

    wangzy2019 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<