摘要:所以就是對象其他的都是類似的。和一樣,既可以數(shù)組形式訪問,也可以按對象方式訪問。大體流程是創(chuàng)建獲取請求對象包括請求頭和請求體注入請求對象到服務(wù)容器配置系統(tǒng)運(yùn)行環(huán)境發(fā)送請求
Laravel Kernel實(shí)例化后的處理
$response = $kernel->handle( $request = IlluminateHttpRequest::capture() );創(chuàng)建并獲取Request對象
$request = IlluminateHttpRequest::capture() IlluminateHttpRequest extends SymfonyComponentHttpFoundationRequest public static function capture() { static::enableHttpMethodParameterOverride(); return static::createFromBase(SymfonyRequest::createFromGlobals()); } public static function enableHttpMethodParameterOverride() { self::$httpMethodParameterOverride = true; } public static function createFromGlobals() { $server = $_SERVER; // CLI mode if ("cli-server" === PHP_SAPI) { if (array_key_exists("HTTP_CONTENT_LENGTH", $_SERVER)) { $server["CONTENT_LENGTH"] = $_SERVER["HTTP_CONTENT_LENGTH"]; } if (array_key_exists("HTTP_CONTENT_TYPE", $_SERVER)) { $server["CONTENT_TYPE"] = $_SERVER["HTTP_CONTENT_TYPE"]; } } // 創(chuàng)建并返回SymfonyComponentHttpFoundationRequest對象,實(shí)際上是用全局變量來實(shí)例化對應(yīng)的類(可以對全局變量進(jìn)行安全過濾),在賦予Request對象 $request = self::createRequestFromFactory($_GET, $_POST, array(), $_COOKIE, $_FILES, $server); // 如果是以PUT|DELETE|PATCH方法進(jìn)行的標(biāo)準(zhǔn)編碼傳輸方式,就從原始數(shù)據(jù)的只讀流解析數(shù)據(jù)到request屬性(此屬性其實(shí)對應(yīng)的是POST鍵值對,PUT|DELETE|PATCH傳輸方式會(huì)被轉(zhuǎn)成POST方式進(jìn)行統(tǒng)一處理) if (0 === strpos($request->headers->get("CONTENT_TYPE"), "application/x-www-form-urlencoded") && in_array(strtoupper($request->server->get("REQUEST_METHOD", "GET")), array("PUT", "DELETE", "PATCH")) ) { parse_str($request->getContent(), $data); $request->request = new ParameterBag($data); } return $request; } private static function createRequestFromFactory(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { // 如果存在自定義的方法,則調(diào)用并返回相應(yīng)的對象 if (self::$requestFactory) { // 此方法必須返回SymfonyComponentHttpFoundationRequest的對象,否則拋異常 $request = call_user_func(self::$requestFactory, $query, $request, $attributes, $cookies, $files, $server, $content); if (!$request instanceof self) { throw new LogicException("The Request factory must return an instance of SymfonyComponentHttpFoundationRequest."); } return $request; } return new static($query, $request, $attributes, $cookies, $files, $server, $content); } // 創(chuàng)建并返回IlluminateHttpRequest對象 public static function createFromBase(SymfonyRequest $request) { if ($request instanceof static) { return $request; } $content = $request->content; $request = (new static)->duplicate( $request->query->all(), $request->request->all(), $request->attributes->all(), $request->cookies->all(), $request->files->all(), $request->server->all() ); $request->content = $content; $request->request = $request->getInputSource(); return $request; } public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null) { return parent::duplicate($query, $request, $attributes, $cookies, $this->filterFiles($files), $server); } public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null) { $dup = clone $this; if ($query !== null) { $dup->query = new ParameterBag($query); } if ($request !== null) { $dup->request = new ParameterBag($request); } if ($attributes !== null) { $dup->attributes = new ParameterBag($attributes); } if ($cookies !== null) { $dup->cookies = new ParameterBag($cookies); } if ($files !== null) { $dup->files = new FileBag($files); } if ($server !== null) { $dup->server = new ServerBag($server); $dup->headers = new HeaderBag($dup->server->getHeaders()); } $dup->languages = null; $dup->charsets = null; $dup->encodings = null; $dup->acceptableContentTypes = null; $dup->pathInfo = null; $dup->requestUri = null; $dup->baseUrl = null; $dup->basePath = null; $dup->method = null; $dup->format = null; if (!$dup->get("_format") && $this->get("_format")) { $dup->attributes->set("_format", $this->get("_format")); } if (!$dup->getRequestFormat(null)) { $dup->setRequestFormat($this->getRequestFormat(null)); } return $dup; } public function getContent($asResource = false) { $currentContentIsResource = is_resource($this->content); if (PHP_VERSION_ID < 50600 && false === $this->content) { throw new LogicException("getContent() can only be called once when using the resource return type and PHP below 5.6."); } // 資源類型時(shí)的處理 if (true === $asResource) { if ($currentContentIsResource) { rewind($this->content); return $this->content; } // Content passed in parameter (test) if (is_string($this->content)) { $resource = fopen("php://temp", "r+"); fwrite($resource, $this->content); rewind($resource); return $resource; } $this->content = false; return fopen("php://input", "rb"); } if ($currentContentIsResource) { rewind($this->content); return stream_get_contents($this->content); } // 否則讀取標(biāo)準(zhǔn)的輸入字節(jié)流 if (null === $this->content || false === $this->content) { $this->content = file_get_contents("php://input"); } return $this->content; }
總之:最后創(chuàng)建了一個(gè)解析了$_GET, $_POST, $_COOKIE, $_FILES, $_SERVER等變量之后的IlluminateHttpRequest類的對象
handle處理(核心)public function handle($request) { try { $request->enableHttpMethodParameterOverride(); $response = $this->sendRequestThroughRouter($request); } catch (Exception $e) { $this->reportException($e); $response = $this->renderException($request, $e); } catch (Throwable $e) { $this->reportException($e = new FatalThrowableError($e)); $response = $this->renderException($request, $e); } event(new EventsRequestHandled($request, $response)); return $response; } // 核心方法 protected function sendRequestThroughRouter($request) { // 注入請求對象到服務(wù)容器,供后期使用 $this->app->instance("request", $request); Facade::clearResolvedInstance("request"); // 啟動(dòng)應(yīng)用(包括加載設(shè)置環(huán)境變量、加載配置文件、設(shè)置系統(tǒng)錯(cuò)誤異常、Facade、啟動(dòng)各服務(wù)提供者的引導(dǎo)項(xiàng)等),后續(xù)分析 $this->bootstrap(); // 委托管道形式處理請求,這個(gè)是middleware實(shí)現(xiàn)的本質(zhì),后續(xù)分析 return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter()); } public static function clearResolvedInstance($name) { unset(static::$resolvedInstance[$name]); } public function bootstrap() { if (! $this->app->hasBeenBootstrapped()) { $this->app->bootstrapWith($this->bootstrappers()); } } protected function bootstrappers() { ##################################################################### #$bootstrappers = [ # IlluminateFoundationBootstrapLoadEnvironmentVariables::class, # IlluminateFoundationBootstrapLoadConfiguration::class, # IlluminateFoundationBootstrapHandleExceptions::class, # IlluminateFoundationBootstrapRegisterFacades::class, # IlluminateFoundationBootstrapRegisterProviders::class, # IlluminateFoundationBootstrapBootProviders::class, #]; ##################################################################### return $this->bootstrappers; } public function bootstrapWith(array $bootstrappers) { $this->hasBeenBootstrapped = true; foreach ($bootstrappers as $bootstrapper) { // 啟動(dòng)前的事件觸發(fā) $this["events"]->fire("bootstrapping: ".$bootstrapper, [$this]); // 創(chuàng)建相應(yīng)的對象并執(zhí)行引導(dǎo)操作 $this->make($bootstrapper)->bootstrap($this); // 啟動(dòng)后的事件觸發(fā) $this["events"]->fire("bootstrapped: ".$bootstrapper, [$this]); } } // 位于IlluminateEventsDispatcher文件,$payload用來傳參給監(jiān)聽器,$halt表示是否終止后續(xù)事件的監(jiān)聽 public function fire($event, $payload = [], $halt = false) { return $this->dispatch($event, $payload, $halt); } public function dispatch($event, $payload = [], $halt = false) { list($event, $payload) = $this->parseEventAndPayload( $event, $payload ); // 若實(shí)現(xiàn)了廣播類則加入廣播隊(duì)列 if ($this->shouldBroadcast($payload)) { $this->broadcastEvent($payload[0]); } $responses = []; // 獲取此事件相關(guān)的監(jiān)聽事件函數(shù) foreach ($this->getListeners($event) as $listener) { $response = $listener($event, $payload); // 觸發(fā)事件 if (! is_null($response) && $halt) { return $response; } if ($response === false) { break; } $responses[] = $response; } return $halt ? null : $responses; } public function getListeners($eventName) { $listeners = isset($this->listeners[$eventName]) ? $this->listeners[$eventName] : []; $listeners = array_merge( $listeners, $this->getWildcardListeners($eventName) ); return class_exists($eventName, false) ? $this->addInterfaceListeners($eventName, $listeners) // 在$listeners增加接口監(jiān)聽事件 : $listeners; }
$this["events"]含義參考[kernel對象化]:
1. IlluminateFoundationApplication extends IlluminateContainerContainer 2. Container implements ArrayAccess,故Application可以按數(shù)組形式讀取。 3. public function offsetGet($key) { return $this->make($key); } 4. public function offsetSet($key, $value) { $this->bind($key, $value instanceof Closure ? $value : function () use ($value) { return $value; });} 5. public function __get($key) { return $this[$key]; } 6. public function __set($key, $value) { $this[$key] = $value; } 7. 所以$this["events"] 就是 $this->instances["events"] 對象($dispatcher); 8. 其他的$this["config"]都是類似的。 9. $this["events"]和$this->events一樣,既可以數(shù)組形式訪問,也可以按對象方式訪問。
大體流程是: 創(chuàng)建獲取請求對象(包括請求頭和請求體)=>注入請求對象到服務(wù)容器=>配置系統(tǒng)運(yùn)行環(huán)境=>發(fā)送請求
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/22610.html
摘要:請求周期加載自動(dòng)加載器獲取應(yīng)用對象實(shí)例化應(yīng)用解析此對象貫穿全文主要過程設(shè)置基礎(chǔ)路徑基礎(chǔ)綁定注冊全局基礎(chǔ)服務(wù)核心容器別名設(shè)置注冊三個(gè)單例獲取對象實(shí)例化此對象為應(yīng)用的樞紐,將會(huì)協(xié)調(diào)各部分之間的工作,完成請求主要過程注入應(yīng)用對象注入事件對象注入 Laravel 請求周期 加載 composer 自動(dòng)加載器 require __DIR__./../bootstrap/autoload.php;...
摘要:請求處理階段請求處理階段首先是準(zhǔn)備請求處理的環(huán)境,包括環(huán)境加載服務(wù)提供者注冊等環(huán)節(jié),然后將請求實(shí)例通過中間件處理及通過路由和控制器的分發(fā)控制,使得不同的請求通過相應(yīng)的處理程序進(jìn)行處理并生成響應(yīng)的過程。 Laravel請求到響應(yīng)的整個(gè)執(zhí)行過程,主要可以歸納為四個(gè)階段,即程序啟動(dòng)準(zhǔn)備階段、請求實(shí)例化階段、請求處理階段、響應(yīng)發(fā)送和程序終止階段。 程序啟動(dòng)準(zhǔn)備階段 服務(wù)容器實(shí)例化 服務(wù)容器的實(shí)...
摘要:初步嘗試既然最常見的注冊命令的方式是修改類中的,那么一般正常人都會(huì)從這邊開始下手。又要自己取出實(shí)例,又要自己調(diào)用方法,調(diào)用方法之前還有自己先把實(shí)例化這么繁瑣,肯定不是運(yùn)行時(shí)添加命令的最佳實(shí)踐,所以我決定繼續(xù)尋找更優(yōu)解。 本文首發(fā)于我的博客,原文鏈接:https://blessing.studio/best-... 雖然 Laravel 官方文檔提供的添加 Artisan Command...
摘要:直到所有中間件都執(zhí)行完畢,最后在執(zhí)行最后的即上述的方法如果上述有地方難懂的,可以參考這邊文章內(nèi)置函數(shù)在中的使用以上是在通過全局中間件時(shí)的大致流程,通過中間件和路由中間件也是一樣的,都是采用管道流操作,詳情可翻閱源碼 簡介 Laravel 中間件提供了一種方便的機(jī)制來過濾進(jìn)入應(yīng)用的 HTTP 請求, 如ValidatePostSize用來驗(yàn)證POST請求體大小、ThrottleReque...
摘要:總結(jié)本文主要學(xué)習(xí)了啟動(dòng)時(shí)做的七步準(zhǔn)備工作環(huán)境檢測配置加載日志配置異常處理注冊注冊啟動(dòng)。 說明:Laravel在把Request通過管道Pipeline送入中間件Middleware和路由Router之前,還做了程序的啟動(dòng)Bootstrap工作,本文主要學(xué)習(xí)相關(guān)源碼,看看Laravel啟動(dòng)程序做了哪些具體工作,并將個(gè)人的研究心得分享出來,希望對別人有所幫助。Laravel在入口index...
閱讀 1468·2021-09-26 09:55
閱讀 1981·2019-08-30 12:45
閱讀 1142·2019-08-29 11:20
閱讀 3614·2019-08-26 11:33
閱讀 3503·2019-08-26 10:55
閱讀 1750·2019-08-23 17:54
閱讀 2470·2019-08-23 15:55
閱讀 2404·2019-08-23 14:23