成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

composer 在laravel中引入文件的過程(文章中有自己的猜想,不是很精煉,想找答案的請左轉(zhuǎn)

luxixing / 1461人閱讀

摘要:在一開始當(dāng)然是的入口文件。里面引入了下的。還是這樣寫吧我曹,到這里在正式開始,然后他進去直接用了下面的方法,所以一切才剛剛開始。。。。。。。。。。

在一開始當(dāng)然是laravel的入口文件server。php 里面引入了public下的index。php
還是這樣寫吧 server.php->public/index.php->bootstarp/autoload.php->vender/autoload.php->composer/autoload_real.php我曹,到這里在正式開始,然后他進去直接用了autoload_real下面的getleader方法,所以一切才剛剛開始。。。。。。。。。。

那么我們來看一下這個getloader方法做了什么
public static function getLoader()

{
    if (null !== self::$loader) {
        return self::$loader;
    }

    spl_autoload_register(array("ComposerAutoloaderInit5e29b2c2d84bb23a17bbe59e2ef81d8f", "loadClassLoader"), true, true);
    self::$loader = $loader = new ComposerAutoloadClassLoader();
    spl_autoload_unregister(array("ComposerAutoloaderInit5e29b2c2d84bb23a17bbe59e2ef81d8f", "loadClassLoader"));

    $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined("HHVM_VERSION");
    if ($useStaticLoader) {
        require_once __DIR__ . "/autoload_static.php";
        call_user_func(ComposerAutoloadComposerStaticInit5e29b2c2d84bb23a17bbe59e2ef81d8f::getInitializer($loader));
    } else {
        $map = require __DIR__ . "/autoload_namespaces.php";
        foreach ($map as $namespace => $path) {
            $loader->set($namespace, $path);
        }
        
        $map = require __DIR__ . "/autoload_psr4.php";
        foreach ($map as $namespace => $path) {
            $loader->setPsr4($namespace, $path);
        }
        $classMap = require __DIR__ . "/autoload_classmap.php";
        if ($classMap) {
            $loader->addClassMap($classMap);
        }
    }

    $loader->register(true);

    if ($useStaticLoader) {
        $includeFiles = ComposerAutoloadComposerStaticInit5e29b2c2d84bb23a17bbe59e2ef81d8f::$files;
    } else {
        $includeFiles = require __DIR__ . "/autoload_files.php";
    }
    foreach ($includeFiles as $fileIdentifier => $file) {
        composerRequire5e29b2c2d84bb23a17bbe59e2ef81d8f($fileIdentifier, $file);
    }
    // var_dump($loader);
    // exit;
    return $loader;
}

首先他進去就先判斷一下$loader這個靜態(tài)變量是不是空的也就是說是一個小的單例,然后開始了注冊loadclassloader這個方法,我曹我剛開始就不知道這個注冊是什么鬼東西,后來才知道這是在php5.xx后使用的東西,之前就是__autoload()這個魔術(shù)方法的進一步使用,也就是在你實例化一個不存在的類是會調(diào)用這個方法,我很奇怪為什么他們不直接調(diào)用這個方法而是選擇用注冊的方式來實現(xiàn),就算是用直接調(diào)用這里也是會在每一次加載進來是運行這個方法,我能想到的作用就是在拋出異常的是時候可以控制,不對是我想錯了,實際是這樣的,這里這個方法只是在autoload.php中調(diào)用,可能在整個框架上的其他地方也有調(diào)用,也就是說在別的地方你new這個類的時候他會跳轉(zhuǎn)到loadclassloader這個方法,這個方法就是幫你include進來這個文件,當(dāng)然了注冊本身就是幫你實例化這個類,之后他就立刻取消了注冊,也就是說在這里只是為了new一下這個類,也就是說現(xiàn)在是沒有加載laravel容器和命名空間和compoer自己的自動加載,這里你要new一個類就得直接require進來之后再實例化,也就是說強行使用了注冊來實例化一個類,如果按照我之前的做法一定是直接require進來文件,然后就實例化了,也就是說這里在我感覺就是強行使代碼優(yōu)雅,畢竟他注冊完就注銷了,這個注冊也就使用這一次,所以不存在外部調(diào)用的情況,好我們繼續(xù)往后看;

接下來出現(xiàn)了php版本的問題,所以laravel針對不同的版本進行處理,然后我就看見了defined(HHVM_VERSION)尼瑪這是什么,在網(wǎng)上看了之后,我整個人都蒙了,我之前的理解是php代碼會被翻譯成C代碼,然后C代碼你們懂得變成機器嗎,然后cpu開始執(zhí)行,現(xiàn)在出現(xiàn)了一個新的叫做字符碼,還有一種叫做即時編譯器的東西叫jit,我大體說一下我在網(wǎng)上看見的,字節(jié)碼是一種專門讓編譯器高效執(zhí)行的代碼,在hhvm首次執(zhí)行php代碼的時候會將所有代碼轉(zhuǎn)成字節(jié)碼然后jit在有請求時會把要運行的字節(jié)碼放在內(nèi)存中,然后編譯成機器碼,也就是說這樣有利于性能的提升,再深就等以后有時間再看了;

好,平復(fù)心情,面對編程這個深不見底的大海,內(nèi)心有些恐慌,我們接著往下看;

在判斷當(dāng)前的php版本大于5.6x并且沒有hhvm之后開始引入autoload_static文件,wait這里我發(fā)現(xiàn)if中用的是requier——once而else里使用的是requier,好我要看看這是怎么回事,我曹,我傻逼了,autoload——static是一個完整的類,而else中是幾個數(shù)組,我們假設(shè)else中也用requier——once來引入,我曹我感覺這里,如果說requier——once用在一個類中是為了節(jié)省性能,那一個數(shù)組是否有必要這樣,還是說laravel框架的開發(fā)者怕出現(xiàn)之前或者之后再來引入這個類導(dǎo)致資源浪費,那如果一個數(shù)組被多次引入會怎么樣,我曹我有傻逼了,在else中引入的各個文件中return的是一個匿名的數(shù)組,也就是說他沒有賦給某個變量,所有不存在什么沖突,好我們再回到之前的流程上;

if中引入文件之后他使用了,函數(shù)回調(diào),我之前不理解函數(shù)回調(diào)有什么意義,如果說他使用靜態(tài)方法時為了提升性能節(jié)約空間,那為什么要使用回調(diào)這種方式,完全可以使用直接調(diào)用的方式,哎,在網(wǎng)上找了一大圈,發(fā)現(xiàn)多數(shù)人說的回調(diào)都是為了高內(nèi)聚,低耦合,這里暫且一筆帶過,其實我之前理解的回調(diào)的用途在與其第二個參數(shù)可以以數(shù)組的形式依次作為函數(shù)的參數(shù),這樣的確很方便。

好了我們接著來看他調(diào)用的部分,Closure我的天這是什么啊,這是怎么引入的,沒有響應(yīng)的命名空間啊,好吧我查了一下,這是一個php自帶的類,
意思是在調(diào)用一個匿名函數(shù)的閉包,當(dāng)然了這里使用了、Closure::bind()有三個參數(shù)第一個自然是一個閉包函數(shù),第二個是對于一個對象的綁定下面有例子,第三個參數(shù)是這個閉包函數(shù)的作用域,我在手冊中看到一個例子,看得我有點蒙,因為我不是很理解第三個參數(shù)的意義,好吧我們先把第二個參數(shù)的例子拿出來看看

ifoo;
};

$bcl1 = Closure::bind($cl1, null, "A");
$bcl2 = Closure::bind($cl2, new A(), "A");
echo $bcl1(), "
";
echo $bcl2(), "
";
?>

就想是js中的$this一樣,表示的是現(xiàn)在正在活動的那個對象,現(xiàn)在我們來看第三個參數(shù)的例子

MetaTrait.php
methods[$methodName] = Closure::bind($methodCallable, $this, get_class());
    }
 
    public function __call($methodName, array $args)
    {
        if (isset($this->methods[$methodName])) {
            return call_user_func_array($this->methods[$methodName], $args);
        }
 
        throw RunTimeException("There is no method with the given name to call");
    }
 
}
?>
test.php
addMethod("when", function () {
    return $this->dayOfWeek;
});
 
echo $test->when();

說實話這個例子我看了很久,我從來沒想到colsure::bind這個方法可以這樣用,如同我們看見的,這個類如同一個工廠一個,你可以創(chuàng)建一個閉包函數(shù),加入到類中,之后就可以直接調(diào)用,并且沒有出現(xiàn)在你本身的類中,要用時只需要use那個類就行,但是目前來說我不知道這種方式有什么好處,回到我們的問題上,在這里的回調(diào)就用的很有意義,因為他的第一個參數(shù)就是一個變量,這意味著每次可能不一樣,并且加上第二個參數(shù)的作用,使得代碼非常的簡潔,配合__call使用味道更佳哦,好我們回到正題,那么第三個參數(shù)在這里有什么做用呢,我看了一下closure::bind的返回值是一個新的對象或者出錯時返回false,那么也就是說在$method中存的是一個對象,我把$method打印了出來是這個樣子,我不知道我們創(chuàng)建的對用的閉包函數(shù)是不是這個methods,于是我做了實驗來確定第三個參數(shù)是什么

于是我就做了這樣的實驗

 trait MetaTrait
    {
       
        public $methods = array();
        public function addMethod($methodName, $methodCallable)
        {
            if (!is_callable($methodCallable)) {
                throw new InvalidArgumentException("Second param must be callable");
            }
            $this->methods[$methodName] = Closure::bind($methodCallable, $this, Fuckyou::class);
            print_r($this->methods);
        }
        public function __call($methodName, array $args)
        {
            if (isset($this->methods[$methodName])) {
                return call_user_func_array($this->methods[$methodName], $args);
            }
            throw RunTimeException("There is no method with the given name to call");
        }
    }
    // require "MetaTrait.php";
    class HackThursday {
        use MetaTrait;
        private $dayOfWeek = "Thursday";
        public function fuck(){
            echo "fuck";
        }
    }
    class Fuckyou {
        use MetaTrait;
        private $fuck = "asd";
    }
    $fuck = new Fuckyou();
    $fuck->addMethod("whenfuck",function (){
        // return 1+1;
        return $this->fuck;
    });
    $test = new HackThursday();
    $test->addMethod("when", function () {
        return $this->dayOfWeek;
         // return 1+1;
    });
    // $m = new HackThursday ();
    // var_dump($m->methods);
    echo $fuck->whenfuck();
    echo $test->when();
    ?>

這個時候輸出

上面fuck類的方法是正常輸出了,但是下邊的顯示沒有權(quán)限訪問,那什么情況下會沒有權(quán)限,我之前是一直沒有理解作用域的意思,我試著把$dayOfWeak的修飾改成public就可以正常顯示。當(dāng)然protected也不行,在切換著3個修飾符的時候我發(fā)現(xiàn)了一個問題,就是在when這個closure這個對象下面的對應(yīng)變量會變,protected就沒有對應(yīng)的類,[dayOfWeek:protected]=>Thursday,然后我試著把第二個參數(shù)改成null,發(fā)現(xiàn)
那也就是說closure這個類,可以規(guī)定綁定那個對象,和這個方法的作用域,也就是說我可以綁定一個類,但是他作用域在另外一個類中?我曹,i"m give up ,我們回到static文件再來看,我曹終于回來了,這種方式可以不再static文件中再引入Classloader就給變量賦值,當(dāng)然也不用吧static文件放在loader_real 文件中,這是一個架空的方法, 那這樣做的好處有什么呢,這樣可以不用再任何一個文件中引入這4個變量,節(jié)省資源,也符合高聚低偶的原則

public static function getInitializer(ClassLoader $loader)
    {
        return Closure::bind(function () use ($loader) {
            $loader->prefixLengthsPsr4 = ComposerStaticInit5e29b2c2d84bb23a17bbe59e2ef81d8f::$prefixLengthsPsr4;
            $loader->prefixDirsPsr4 = ComposerStaticInit5e29b2c2d84bb23a17bbe59e2ef81d8f::$prefixDirsPsr4;
            $loader->prefixesPsr0 = ComposerStaticInit5e29b2c2d84bb23a17bbe59e2ef81d8f::$prefixesPsr0;
            $loader->classMap = ComposerStaticInit5e29b2c2d84bb23a17bbe59e2ef81d8f::$classMap;
  
        }, null, ClassLoader::class);


    }

我的天,一直到這里我們解釋了autoload_real48行代碼,迎來了這個類的核心功能$loader->register(true);

public function register($prepend = false)
    {
        spl_autoload_register(array($this, "loadClass"), true, $prepend);
    }

這行代碼,注冊了loadClass這個方法,后面兩個參數(shù)第2個表示是否拋出異常,第三個表示是否在隊列之首

public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            includeFile($file);
            return true;
        }
    }

這里傳過來一個想要調(diào)用的類名,然后$this->findFile($class)去找對應(yīng)的路徑,如果存在就引入,注意這里return了true也就是說沒有return的話就會拋出異常

public function findFile($class)
    {
        // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
        if ("" == $class[0]) {
            $class = substr($class, 1);
        }
        // class map lookup
        if (isset($this->classMap[$class])) {
            return $this->classMap[$class];
        }
        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
            return false;
        }
        $file = $this->findFileWithExtension($class, ".php");
        // Search for Hack files if we are running on HHVM
        if (false === $file && defined("HHVM_VERSION")) {
            $file = $this->findFileWithExtension($class, ".hh");
        }
        if (false === $file) {
            // Remember that this class does not exist.
            $this->missingClasses[$class] = true;
        }
        return $file;
    }

我們來一行一行看$class[0]?,這是什么$class不是一個數(shù)組啊我測試之后顯示是要引入類的第一個字母,還有這種操作?
那他就是刪除了要引入類名的第一,像是這樣
call_user_func(ComposerAutoloadComposerStaticInit5e29b2c2d84bb23a17bbe59e2ef81d8f::getInitializer($loader));
然后在classmap里面找,$this->classMapAuthoritative這個變量沒有被賦值啊,我翻譯了一下是權(quán)威性的意思,沒事我們先看一下他判斷后做了什么。。。。。
return 了false這里先不談,可能是出于別的需求會阻止引入

private function findFileWithExtension($class, $ext)
    {
        // PSR-4 lookup
        $logicalPathPsr4 = strtr($class, "", DIRECTORY_SEPARATOR) . $ext;
        $first = $class[0];
        if (isset($this->prefixLengthsPsr4[$first])) {
            foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
                if (0 === strpos($class, $prefix)) {
                    foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
                            return $file;
                        }
                    }
                }
            }
        }
        // PSR-4 fallback dirs
        foreach ($this->fallbackDirsPsr4 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
                return $file;
            }
        }
        // PSR-0 lookup
        if (false !== $pos = strrpos($class, "")) {
            // namespaced class name
            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
                . strtr(substr($logicalPathPsr4, $pos + 1), "_", DIRECTORY_SEPARATOR);
        } else {
            // PEAR-like class name
            $logicalPathPsr0 = strtr($class, "_", DIRECTORY_SEPARATOR) . $ext;
        }
        if (isset($this->prefixesPsr0[$first])) {
            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
                if (0 === strpos($class, $prefix)) {
                    foreach ($dirs as $dir) {
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                            return $file;
                        }
                    }
                }
            }
        }
        // PSR-0 fallback dirs
        foreach ($this->fallbackDirsPsr0 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                return $file;
            }
        }
        // PSR-0 include paths.
        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
            return $file;
        }
        return false;
    }
}

DIRECTORY_SEPARATOR這個變量是一個php自帶的變量不需要聲明或者定義就可以使用,就是在win環(huán)境或者liunx環(huán)境中的文件分割符會根據(jù)不同的環(huán)境顯示
在win環(huán)境中顯示的是linux環(huán)境就是/,PSR4抬頭這里就是將進來的 $class中的變成/然后在$this->prefixLengthsPsr4中找對應(yīng)的命名空間和對應(yīng)的length
然后在$this->prefixDirsPsr4在下找對應(yīng)的命名空間的路徑然后return這個路徑,之后的psr0也是根據(jù)psr0的規(guī)則來處理命名空間,我猜他的第一個路徑一定不能有下劃線,在psr0中用下劃線來代表文件分割符,綜上這個方法會返回一個路徑。

接著我們繼續(xù)往下看,判斷沒有對應(yīng)的路徑并且支持HHVM就會把后綴改成.hh然后在調(diào)用$this->findFileWithExtension這個方法,這個方法中l(wèi)aravel對于兩種格式做了相應(yīng)的調(diào)整,所以我在這里想說,能用一個方法解決的絕對不用一個半,這樣才簡介。

當(dāng)然了之后就引入了,這篇文章就是這樣,隨后可能還會更新,總體來說第一次寫技術(shù)博客,文章有很多地方都是我自己的猜想,按理說這不應(yīng)該出現(xiàn)在這里,但是我覺得這樣有利于我集中精神,好了結(jié)束,歡迎大家補充或支出錯誤

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/25678.html

相關(guān)文章

  • 現(xiàn)寫 PHP,你應(yīng)該知道這些

    摘要:首先你應(yīng)該是在用以上的版本,如果版本在這之下,是時候該升級了。按照其官網(wǎng)的說法,這個組織的目的并不是告訴你你應(yīng)該怎么做,只是一些主流的框架之間相互協(xié)商和約定。和沒有出現(xiàn)在以上的列表中,是因為還沒有投票通過。不要被這些話所困擾。 首先你應(yīng)該是在用 PHP 5.3 以上的版本,如果 PHP 版本在這之下,是時候該升級了。我建議如果有條件,最好使用最新的版本。 你應(yīng)該看過 PHP The R...

    supernavy 評論0 收藏0
  • 記一次PHP并發(fā)性能調(diào)優(yōu)實戰(zhàn) -- 性能提升104%

    摘要:這是多處理器系統(tǒng)中,調(diào)度器用來分散任務(wù)到不同的機制,通常也被稱為處理器間中斷,。文章編寫計劃 待完成: 詳細介紹用到的各個工具 作者: 萬千鈞(祝星) 適合閱讀人群 文中的調(diào)優(yōu)思路無論是php, java, 還是其他任何語言都是用. 如果你有php使用經(jīng)驗, 那肯定就更好了 業(yè)務(wù)背景 框架及相應(yīng)環(huán)境 laravel5.7, mysql5.7, redis5, nginx1.15 cento...

    番茄西紅柿 評論0 收藏0
  • 記一次PHP并發(fā)性能調(diào)優(yōu)實戰(zhàn) -- 性能提升104%

    摘要:這是多處理器系統(tǒng)中,調(diào)度器用來分散任務(wù)到不同的機制,通常也被稱為處理器間中斷,。文章編寫計劃 待完成: 詳細介紹用到的各個工具 作者: 萬千鈞(祝星) 適合閱讀人群 文中的調(diào)優(yōu)思路無論是php, java, 還是其他任何語言都是用. 如果你有php使用經(jīng)驗, 那肯定就更好了 業(yè)務(wù)背景 框架及相應(yīng)環(huán)境 laravel5.7, mysql5.7, redis5, nginx1.15 cento...

    xeblog 評論0 收藏0
  • PHP程序員如何優(yōu)雅搬磚

    摘要:這是年前的最后一篇文章,本章來聊一聊程序員如何優(yōu)雅的搬磚搬磚既為達到目的,不斷重復(fù)某項工作的行為,其實與造輪子一樣,不謀而合基礎(chǔ)這里的基礎(chǔ)并非單指其技術(shù)能力,技術(shù)底蘊,更有意體現(xiàn)程序員在初期不斷重復(fù)的工作而獲得的感想與意識。 showImg(https://segmentfault.com/img/bVbnSFx?w=800&h=444); 我一生的文章都會放在這里,我的博客,我希望每...

    妤鋒シ 評論0 收藏0
  • Wizard 開源文檔管理系統(tǒng)1.0發(fā)布啦

    摘要:總結(jié)如果你在為公司尋找一款開源免費的開發(fā)文檔文檔管理工具,不妨考慮一下項目,一定不會讓你失望的。 Wizard 是一款開源文檔管理系統(tǒng),項目地址為 https://github.com/mylxsw/wizard。這個項目是 我 在2017年就開始開發(fā)的,起初只是想做一款能夠在公司內(nèi)部把Swagger文檔管理起來的工具,但在這近兩年的時間里,一直斷斷續(xù)續(xù)的為其添加各種功能,現(xiàn)在終于下決...

    cod7ce 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<