摘要:在一開(kāi)始當(dāng)然是的入口文件。里面引入了下的。還是這樣寫(xiě)吧我曹,到這里在正式開(kāi)始,然后他進(jìn)去直接用了下面的方法,所以一切才剛剛開(kāi)始。。。。。。。。。。
在一開(kāi)始當(dāng)然是laravel的入口文件server。php 里面引入了public下的index。php
還是這樣寫(xiě)吧 server.php->public/index.php->bootstarp/autoload.php->vender/autoload.php->composer/autoload_real.php我曹,到這里在正式開(kāi)始,然后他進(jìn)去直接用了autoload_real下面的getleader方法,所以一切才剛剛開(kāi)始。。。。。。。。。。
那么我們來(lái)看一下這個(gè)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; }
首先他進(jìn)去就先判斷一下$loader這個(gè)靜態(tài)變量是不是空的也就是說(shuō)是一個(gè)小的單例,然后開(kāi)始了注冊(cè)loadclassloader這個(gè)方法,我曹我剛開(kāi)始就不知道這個(gè)注冊(cè)是什么鬼東西,后來(lái)才知道這是在php5.xx后使用的東西,之前就是__autoload()這個(gè)魔術(shù)方法的進(jìn)一步使用,也就是在你實(shí)例化一個(gè)不存在的類(lèi)是會(huì)調(diào)用這個(gè)方法,我很奇怪為什么他們不直接調(diào)用這個(gè)方法而是選擇用注冊(cè)的方式來(lái)實(shí)現(xiàn),就算是用直接調(diào)用這里也是會(huì)在每一次加載進(jìn)來(lái)是運(yùn)行這個(gè)方法,我能想到的作用就是在拋出異常的是時(shí)候可以控制,不對(duì)是我想錯(cuò)了,實(shí)際是這樣的,這里這個(gè)方法只是在autoload.php中調(diào)用,可能在整個(gè)框架上的其他地方也有調(diào)用,也就是說(shuō)在別的地方你new這個(gè)類(lèi)的時(shí)候他會(huì)跳轉(zhuǎn)到loadclassloader這個(gè)方法,這個(gè)方法就是幫你include進(jìn)來(lái)這個(gè)文件,當(dāng)然了注冊(cè)本身就是幫你實(shí)例化這個(gè)類(lèi),之后他就立刻取消了注冊(cè),也就是說(shuō)在這里只是為了new一下這個(gè)類(lèi),也就是說(shuō)現(xiàn)在是沒(méi)有加載laravel容器和命名空間和compoer自己的自動(dòng)加載,這里你要new一個(gè)類(lèi)就得直接require進(jìn)來(lái)之后再實(shí)例化,也就是說(shuō)強(qiáng)行使用了注冊(cè)來(lái)實(shí)例化一個(gè)類(lèi),如果按照我之前的做法一定是直接require進(jìn)來(lái)文件,然后就實(shí)例化了,也就是說(shuō)這里在我感覺(jué)就是強(qiáng)行使代碼優(yōu)雅,畢竟他注冊(cè)完就注銷(xiāo)了,這個(gè)注冊(cè)也就使用這一次,所以不存在外部調(diào)用的情況,好我們繼續(xù)往后看;
接下來(lái)出現(xiàn)了php版本的問(wèn)題,所以laravel針對(duì)不同的版本進(jìn)行處理,然后我就看見(jiàn)了defined(HHVM_VERSION)尼瑪這是什么,在網(wǎng)上看了之后,我整個(gè)人都蒙了,我之前的理解是php代碼會(huì)被翻譯成C代碼,然后C代碼你們懂得變成機(jī)器嗎,然后cpu開(kāi)始執(zhí)行,現(xiàn)在出現(xiàn)了一個(gè)新的叫做字符碼,還有一種叫做即時(shí)編譯器的東西叫jit,我大體說(shuō)一下我在網(wǎng)上看見(jiàn)的,字節(jié)碼是一種專(zhuān)門(mén)讓編譯器高效執(zhí)行的代碼,在hhvm首次執(zhí)行php代碼的時(shí)候會(huì)將所有代碼轉(zhuǎn)成字節(jié)碼然后jit在有請(qǐng)求時(shí)會(huì)把要運(yùn)行的字節(jié)碼放在內(nèi)存中,然后編譯成機(jī)器碼,也就是說(shuō)這樣有利于性能的提升,再深就等以后有時(shí)間再看了;
好,平復(fù)心情,面對(duì)編程這個(gè)深不見(jiàn)底的大海,內(nèi)心有些恐慌,我們接著往下看;
在判斷當(dāng)前的php版本大于5.6x并且沒(méi)有hhvm之后開(kāi)始引入autoload_static文件,wait這里我發(fā)現(xiàn)if中用的是requier——once而else里使用的是requier,好我要看看這是怎么回事,我曹,我傻逼了,autoload——static是一個(gè)完整的類(lèi),而else中是幾個(gè)數(shù)組,我們假設(shè)else中也用requier——once來(lái)引入,我曹我感覺(jué)這里,如果說(shuō)requier——once用在一個(gè)類(lèi)中是為了節(jié)省性能,那一個(gè)數(shù)組是否有必要這樣,還是說(shuō)laravel框架的開(kāi)發(fā)者怕出現(xiàn)之前或者之后再來(lái)引入這個(gè)類(lèi)導(dǎo)致資源浪費(fèi),那如果一個(gè)數(shù)組被多次引入會(huì)怎么樣,我曹我有傻逼了,在else中引入的各個(gè)文件中return的是一個(gè)匿名的數(shù)組,也就是說(shuō)他沒(méi)有賦給某個(gè)變量,所有不存在什么沖突,好我們?cè)倩氐街暗牧鞒躺希?/p>
if中引入文件之后他使用了,函數(shù)回調(diào),我之前不理解函數(shù)回調(diào)有什么意義,如果說(shuō)他使用靜態(tài)方法時(shí)為了提升性能節(jié)約空間,那為什么要使用回調(diào)這種方式,完全可以使用直接調(diào)用的方式,哎,在網(wǎng)上找了一大圈,發(fā)現(xiàn)多數(shù)人說(shuō)的回調(diào)都是為了高內(nèi)聚,低耦合,這里暫且一筆帶過(guò),其實(shí)我之前理解的回調(diào)的用途在與其第二個(gè)參數(shù)可以以數(shù)組的形式依次作為函數(shù)的參數(shù),這樣的確很方便。
好了我們接著來(lái)看他調(diào)用的部分,Closure我的天這是什么啊,這是怎么引入的,沒(méi)有響應(yīng)的命名空間啊,好吧我查了一下,這是一個(gè)php自帶的類(lèi),
意思是在調(diào)用一個(gè)匿名函數(shù)的閉包,當(dāng)然了這里使用了、Closure::bind()有三個(gè)參數(shù)第一個(gè)自然是一個(gè)閉包函數(shù),第二個(gè)是對(duì)于一個(gè)對(duì)象的綁定下面有例子,第三個(gè)參數(shù)是這個(gè)閉包函數(shù)的作用域,我在手冊(cè)中看到一個(gè)例子,看得我有點(diǎn)蒙,因?yàn)槲也皇呛芾斫獾谌齻€(gè)參數(shù)的意義,好吧我們先把第二個(gè)參數(shù)的例子拿出來(lái)看看
ifoo; }; $bcl1 = Closure::bind($cl1, null, "A"); $bcl2 = Closure::bind($cl2, new A(), "A"); echo $bcl1(), " "; echo $bcl2(), " "; ?>
就想是js中的$this一樣,表示的是現(xiàn)在正在活動(dòng)的那個(gè)對(duì)象,現(xiàn)在我們來(lái)看第三個(gè)參數(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();
說(shuō)實(shí)話(huà)這個(gè)例子我看了很久,我從來(lái)沒(méi)想到colsure::bind這個(gè)方法可以這樣用,如同我們看見(jiàn)的,這個(gè)類(lèi)如同一個(gè)工廠一個(gè),你可以創(chuàng)建一個(gè)閉包函數(shù),加入到類(lèi)中,之后就可以直接調(diào)用,并且沒(méi)有出現(xiàn)在你本身的類(lèi)中,要用時(shí)只需要use那個(gè)類(lèi)就行,但是目前來(lái)說(shuō)我不知道這種方式有什么好處,回到我們的問(wèn)題上,在這里的回調(diào)就用的很有意義,因?yàn)樗牡谝粋€(gè)參數(shù)就是一個(gè)變量,這意味著每次可能不一樣,并且加上第二個(gè)參數(shù)的作用,使得代碼非常的簡(jiǎn)潔,配合__call使用味道更佳哦,好我們回到正題,那么第三個(gè)參數(shù)在這里有什么做用呢,我看了一下closure::bind的返回值是一個(gè)新的對(duì)象或者出錯(cuò)時(shí)返回false,那么也就是說(shuō)在$method中存的是一個(gè)對(duì)象,我把$method打印了出來(lái)是這個(gè)樣子,我不知道我們創(chuàng)建的對(duì)用的閉包函數(shù)是不是這個(gè)methods,于是我做了實(shí)驗(yàn)來(lái)確定第三個(gè)參數(shù)是什么
于是我就做了這樣的實(shí)驗(yàn)
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(); ?>
這個(gè)時(shí)候輸出
上面fuck類(lèi)的方法是正常輸出了,但是下邊的顯示沒(méi)有權(quán)限訪問(wèn),那什么情況下會(huì)沒(méi)有權(quán)限,我之前是一直沒(méi)有理解作用域的意思,我試著把$dayOfWeak的修飾改成public就可以正常顯示。當(dāng)然protected也不行,在切換著3個(gè)修飾符的時(shí)候我發(fā)現(xiàn)了一個(gè)問(wèn)題,就是在when這個(gè)closure這個(gè)對(duì)象下面的對(duì)應(yīng)變量會(huì)變,protected就沒(méi)有對(duì)應(yīng)的類(lèi),[dayOfWeek:protected]=>Thursday,然后我試著把第二個(gè)參數(shù)改成null,發(fā)現(xiàn)
那也就是說(shuō)closure這個(gè)類(lèi),可以規(guī)定綁定那個(gè)對(duì)象,和這個(gè)方法的作用域,也就是說(shuō)我可以綁定一個(gè)類(lèi),但是他作用域在另外一個(gè)類(lèi)中?我曹,i"m give up ,我們回到static文件再來(lái)看,我曹終于回來(lái)了,這種方式可以不再static文件中再引入Classloader就給變量賦值,當(dāng)然也不用吧static文件放在loader_real 文件中,這是一個(gè)架空的方法, 那這樣做的好處有什么呢,這樣可以不用再任何一個(gè)文件中引入這4個(gè)變量,節(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行代碼,迎來(lái)了這個(gè)類(lèi)的核心功能$loader->register(true);
public function register($prepend = false) { spl_autoload_register(array($this, "loadClass"), true, $prepend); }
這行代碼,注冊(cè)了loadClass這個(gè)方法,后面兩個(gè)參數(shù)第2個(gè)表示是否拋出異常,第三個(gè)表示是否在隊(duì)列之首
public function loadClass($class) { if ($file = $this->findFile($class)) { includeFile($file); return true; } }
這里傳過(guò)來(lái)一個(gè)想要調(diào)用的類(lèi)名,然后$this->findFile($class)去找對(duì)應(yīng)的路徑,如果存在就引入,注意這里return了true也就是說(shuō)沒(méi)有return的話(huà)就會(huì)拋出異常
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; }
我們來(lái)一行一行看$class[0]?,這是什么$class不是一個(gè)數(shù)組啊我測(cè)試之后顯示是要引入類(lèi)的第一個(gè)字母,還有這種操作?
那他就是刪除了要引入類(lèi)名的第一,像是這樣
call_user_func(ComposerAutoloadComposerStaticInit5e29b2c2d84bb23a17bbe59e2ef81d8f::getInitializer($loader));
然后在classmap里面找,$this->classMapAuthoritative這個(gè)變量沒(méi)有被賦值啊,我翻譯了一下是權(quán)威性的意思,沒(méi)事我們先看一下他判斷后做了什么。。。。。
return 了false這里先不談,可能是出于別的需求會(huì)阻止引入
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這個(gè)變量是一個(gè)php自帶的變量不需要聲明或者定義就可以使用,就是在win環(huán)境或者liunx環(huán)境中的文件分割符會(huì)根據(jù)不同的環(huán)境顯示
在win環(huán)境中顯示的是linux環(huán)境就是/,PSR4抬頭這里就是將進(jìn)來(lái)的 $class中的變成/然后在$this->prefixLengthsPsr4中找對(duì)應(yīng)的命名空間和對(duì)應(yīng)的length
然后在$this->prefixDirsPsr4在下找對(duì)應(yīng)的命名空間的路徑然后return這個(gè)路徑,之后的psr0也是根據(jù)psr0的規(guī)則來(lái)處理命名空間,我猜他的第一個(gè)路徑一定不能有下劃線,在psr0中用下劃線來(lái)代表文件分割符,綜上這個(gè)方法會(huì)返回一個(gè)路徑。
接著我們繼續(xù)往下看,判斷沒(méi)有對(duì)應(yīng)的路徑并且支持HHVM就會(huì)把后綴改成.hh然后在調(diào)用$this->findFileWithExtension這個(gè)方法,這個(gè)方法中l(wèi)aravel對(duì)于兩種格式做了相應(yīng)的調(diào)整,所以我在這里想說(shuō),能用一個(gè)方法解決的絕對(duì)不用一個(gè)半,這樣才簡(jiǎn)介。
當(dāng)然了之后就引入了,這篇文章就是這樣,隨后可能還會(huì)更新,總體來(lái)說(shuō)第一次寫(xiě)技術(shù)博客,文章有很多地方都是我自己的猜想,按理說(shuō)這不應(yīng)該出現(xiàn)在這里,但是我覺(jué)得這樣有利于我集中精神,好了結(jié)束,歡迎大家補(bǔ)充或支出錯(cuò)誤
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/25678.html
摘要:首先你應(yīng)該是在用以上的版本,如果版本在這之下,是時(shí)候該升級(jí)了。按照其官網(wǎng)的說(shuō)法,這個(gè)組織的目的并不是告訴你你應(yīng)該怎么做,只是一些主流的框架之間相互協(xié)商和約定。和沒(méi)有出現(xiàn)在以上的列表中,是因?yàn)檫€沒(méi)有投票通過(guò)。不要被這些話(huà)所困擾。 首先你應(yīng)該是在用 PHP 5.3 以上的版本,如果 PHP 版本在這之下,是時(shí)候該升級(jí)了。我建議如果有條件,最好使用最新的版本。 你應(yīng)該看過(guò) PHP The R...
摘要:這是多處理器系統(tǒng)中,調(diào)度器用來(lái)分散任務(wù)到不同的機(jī)制,通常也被稱(chēng)為處理器間中斷,。文章編寫(xiě)計(jì)劃 待完成: 詳細(xì)介紹用到的各個(gè)工具 作者: 萬(wàn)千鈞(祝星) 適合閱讀人群 文中的調(diào)優(yōu)思路無(wú)論是php, java, 還是其他任何語(yǔ)言都是用. 如果你有php使用經(jīng)驗(yàn), 那肯定就更好了 業(yè)務(wù)背景 框架及相應(yīng)環(huán)境 laravel5.7, mysql5.7, redis5, nginx1.15 cento...
摘要:這是多處理器系統(tǒng)中,調(diào)度器用來(lái)分散任務(wù)到不同的機(jī)制,通常也被稱(chēng)為處理器間中斷,。文章編寫(xiě)計(jì)劃 待完成: 詳細(xì)介紹用到的各個(gè)工具 作者: 萬(wàn)千鈞(祝星) 適合閱讀人群 文中的調(diào)優(yōu)思路無(wú)論是php, java, 還是其他任何語(yǔ)言都是用. 如果你有php使用經(jīng)驗(yàn), 那肯定就更好了 業(yè)務(wù)背景 框架及相應(yīng)環(huán)境 laravel5.7, mysql5.7, redis5, nginx1.15 cento...
摘要:這是年前的最后一篇文章,本章來(lái)聊一聊程序員如何優(yōu)雅的搬磚搬磚既為達(dá)到目的,不斷重復(fù)某項(xiàng)工作的行為,其實(shí)與造輪子一樣,不謀而合基礎(chǔ)這里的基礎(chǔ)并非單指其技術(shù)能力,技術(shù)底蘊(yùn),更有意體現(xiàn)程序員在初期不斷重復(fù)的工作而獲得的感想與意識(shí)。 showImg(https://segmentfault.com/img/bVbnSFx?w=800&h=444); 我一生的文章都會(huì)放在這里,我的博客,我希望每...
摘要:總結(jié)如果你在為公司尋找一款開(kāi)源免費(fèi)的開(kāi)發(fā)文檔文檔管理工具,不妨考慮一下項(xiàng)目,一定不會(huì)讓你失望的。 Wizard 是一款開(kāi)源文檔管理系統(tǒng),項(xiàng)目地址為 https://github.com/mylxsw/wizard。這個(gè)項(xiàng)目是 我 在2017年就開(kāi)始開(kāi)發(fā)的,起初只是想做一款能夠在公司內(nèi)部把Swagger文檔管理起來(lái)的工具,但在這近兩年的時(shí)間里,一直斷斷續(xù)續(xù)的為其添加各種功能,現(xiàn)在終于下決...
閱讀 2626·2021-10-08 10:17
閱讀 1982·2021-09-06 15:02
閱讀 2665·2019-08-29 17:30
閱讀 2789·2019-08-29 13:24
閱讀 1652·2019-08-29 11:12
閱讀 3477·2019-08-28 17:52
閱讀 788·2019-08-26 11:30
閱讀 3725·2019-08-26 11:01