真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Laravel的生命周期實(shí)例分析

本篇內(nèi)容主要講解“Laravel的生命周期實(shí)例分析”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Laravel的生命周期實(shí)例分析”吧!

創(chuàng)新互聯(lián)建站專業(yè)為企業(yè)提供長(zhǎng)安網(wǎng)站建設(shè)、長(zhǎng)安做網(wǎng)站、長(zhǎng)安網(wǎng)站設(shè)計(jì)、長(zhǎng)安網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、長(zhǎng)安企業(yè)網(wǎng)站模板建站服務(wù),10余年長(zhǎng)安做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

Laravel的生命周期 A

世間萬(wàn)物皆有生命周期,當(dāng)我們使用任何工具時(shí)都需要理解它的工作原理,那么用起來(lái)就會(huì)得心應(yīng)手,應(yīng)用開(kāi)發(fā)也是如此。理解了它的原理,那么使用起來(lái)就會(huì)游刃有余。

在了解 Laravel 的生命周期前,我們先回顧一下PHP 的生命周期。

PHP 的運(yùn)行模式

PHP兩種運(yùn)行模式是WEB模式、CLI模式。

當(dāng)我們?cè)诮K端敲入php這個(gè)命令的時(shí)候,使用的是CLI模式。

當(dāng)使用Nginx或者別web服務(wù)器作為宿主處理一個(gè)到來(lái)的請(qǐng)求時(shí),使用的是WEB模式。

PHP 的生命周期

當(dāng)我們請(qǐng)求一個(gè)php文件時(shí),PHP 為了完成這次請(qǐng)求,會(huì)發(fā)生5個(gè)階段的生命周期切換:

  • 1 模塊初始化(MINIT),即調(diào)用 php.ini 中指明的擴(kuò)展的初始化函數(shù)進(jìn)行初始化工作,如 MySQL 擴(kuò)展。

  • 2 請(qǐng)求初始化(RINIT),即初始化為執(zhí)行本次腳本所需要的變量名稱和變量值內(nèi)容的符號(hào)表,如 $_SESSION變量。

  • 3 執(zhí)行該P(yáng)HP腳本。

  • 4 請(qǐng)求處理完成(Request Shutdown),按順序調(diào)用各個(gè)模塊的 RSHUTDOWN 方法,對(duì)每個(gè)變量調(diào)用 unset 函數(shù),如 unset $_SESSION 變量。

  • 5 關(guān)閉模塊(Module Shutdown) , PHP調(diào)用每個(gè)擴(kuò)展的 MSHUTDOWN 方法,這是各個(gè)模塊最后一次釋放內(nèi)存的機(jī)會(huì)。這意味著沒(méi)有下一個(gè)請(qǐng)求了。

WEB模式和CLI(命令行)模式很相似,區(qū)別是:

CLI 模式會(huì)在每次腳本執(zhí)行經(jīng)歷完整的5個(gè)周期,因?yàn)槟隳_本執(zhí)行完不會(huì)有下一個(gè)請(qǐng)求;

WEB模式為了應(yīng)對(duì)并發(fā),可能采用多線程,因此生命周期1和5有可能只執(zhí)行一次,下次請(qǐng)求到來(lái)時(shí)重復(fù)2-4的生命周期,這樣就節(jié)省了系統(tǒng)模塊初始化所帶來(lái)的開(kāi)銷。

可以看出PHP生命周期是很對(duì)稱的。說(shuō)了這么多,就是為了定位Laravel運(yùn)行在哪里,沒(méi)錯(cuò),Laravel僅僅運(yùn)行再 第三個(gè)階段:

作用

理解這些,你就可以優(yōu)化你的 Laravel 代碼,可以更加深入的了解 Laravel 的singleton(單例)。

至少你知道了,每一次請(qǐng)求結(jié)束,PHP 的變量都會(huì) unset,Laravel 的 singleton 只是在某一次請(qǐng)求過(guò)程中的singleton;

你在 Laravel 中的靜態(tài)變量也不能在多個(gè)請(qǐng)求之間共享,因?yàn)槊恳淮握?qǐng)求結(jié)束都會(huì) unset。

理解這些概念,是寫高質(zhì)量代碼的第一步,也是最關(guān)鍵的一步。因此記住,PHP是一種腳本語(yǔ)言,所有的變量只會(huì)在這一次請(qǐng)求中生效,下次請(qǐng)求之時(shí)已被重置,而不像Java靜態(tài)變量擁有全局作用。

Laravel 的生命周期

概述

Laravel 的生命周期從public\index.php開(kāi)始,從public\index.php結(jié)束。

請(qǐng)求過(guò)程

下面是 public\index.php的全部源碼,更具體來(lái)說(shuō)可以分為四步:

make(Illuminate\Contracts\Http\Kernel::class);

$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

$response->send();

$kernel->terminate($request, $response);

以下是四步詳細(xì)的解釋是:composer自動(dòng)加載需要的類

  • 1 文件載入composer生成的自動(dòng)加載設(shè)置,包括所有你 composer require的依賴。

  • 2 生成容器 Container,Application實(shí)例,并向容器注冊(cè)核心組件(HttpKernel,ConsoleKernel ,ExceptionHandler)(對(duì)應(yīng)代碼2,容器很重要,后面詳細(xì)講解)。

  • 3 處理請(qǐng)求,生成并發(fā)送響應(yīng)(對(duì)應(yīng)代碼3,毫不夸張的說(shuō),你99%的代碼都運(yùn)行在這個(gè)小小的handle 方法里面)。

  • 4 請(qǐng)求結(jié)束,進(jìn)行回調(diào)(對(duì)應(yīng)代碼4,還記得可終止中間件嗎?沒(méi)錯(cuò),就是在這里回調(diào)的)。

Laravel 的請(qǐng)求步驟

第一步:注冊(cè)加載composer自動(dòng)生成的class loader
就是加載初始化第三方依賴。

第二步:生成容器 Container
并向容器注冊(cè)核心組件,是從 bootstrap/app.php 腳本獲取 Laravel 應(yīng)用實(shí)例,

第三步:這一步是重點(diǎn),處理請(qǐng)求,并生成發(fā)送響應(yīng)。
請(qǐng)求被發(fā)送到 HTTP 內(nèi)核或 Console 內(nèi)核,這取決于進(jìn)入應(yīng)用的請(qǐng)求類型。

取決于是通過(guò)瀏覽器請(qǐng)求還是通過(guò)控制臺(tái)請(qǐng)求。這里我們主要是通過(guò)瀏覽器請(qǐng)求。

HTTP 內(nèi)核繼承自 Illuminate\Foundation\Http\Kernel 類,該類定義了一個(gè) bootstrappers 數(shù)組,這個(gè)數(shù)組中的類在請(qǐng)求被執(zhí)行前運(yùn)行,這些 bootstrappers 配置了錯(cuò)誤處理、日志、檢測(cè)應(yīng)用環(huán)境以及其它在請(qǐng)求被處理前需要執(zhí)行的任務(wù)。

protected $bootstrappers = [        //注冊(cè)系統(tǒng)環(huán)境配置 (.env)        'Illuminate\Foundation\Bootstrap\DetectEnvironment',        //注冊(cè)系統(tǒng)配置(config)        'Illuminate\Foundation\Bootstrap\LoadConfiguration',        //注冊(cè)日志配置        'Illuminate\Foundation\Bootstrap\ConfigureLogging',        //注冊(cè)異常處理        'Illuminate\Foundation\Bootstrap\HandleExceptions',        //注冊(cè)服務(wù)容器的門面,F(xiàn)acade 是個(gè)提供從容器訪問(wèn)對(duì)象的類。        'Illuminate\Foundation\Bootstrap\RegisterFacades',        //注冊(cè)服務(wù)提供者        'Illuminate\Foundation\Bootstrap\RegisterProviders',        //注冊(cè)服務(wù)提供者 `boot`        'Illuminate\Foundation\Bootstrap\BootProviders',    ];

Laravel的生命周期 B

laravel/public/index.php

/**
 * laravel的啟動(dòng)時(shí)間
 */
define('LARAVEL_START', microtime(true));

/**
 * 加載項(xiàng)目依賴。
 * 現(xiàn)代PHP依賴于Composer包管理器,入口文件通過(guò)引入由Composer包管理器。
 * 自動(dòng)生成的類加載程序,可以輕松注冊(cè)并加載所依賴的第三方組件庫(kù)。
 */
require __DIR__.'/../vendor/autoload.php';

/**
 * 創(chuàng)建laravel應(yīng)用實(shí)例。
 */
$app = require_once __DIR__.'/../bootstrap/app.php';

// 接受請(qǐng)求并響應(yīng)
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

// 結(jié)束請(qǐng)求,進(jìn)行回調(diào)
$response->send();

// 終止程序
$kernel->terminate($request, $response);

laravel/boostrap/app.php

# 第一部分:創(chuàng)建應(yīng)用實(shí)例
$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.'/../')
);

# 第二部分:完成內(nèi)核綁定
$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Http\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Console\Kernel::class
);

$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);

return $app;

laravel\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php

class Kernel implements KernelContract
{
    protected $bootstrappers = [
        \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class, // 注冊(cè)系統(tǒng)環(huán)境配置
        \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,              // 注冊(cè)系統(tǒng)配置 
        \Illuminate\Foundation\Bootstrap\HandleExceptions::class,              // 注冊(cè)異常注冊(cè)
        \Illuminate\Foundation\Bootstrap\RegisterFacades::class,                // 注冊(cè)門面模式
        \Illuminate\Foundation\Bootstrap\RegisterProviders::class,              // 注冊(cè)服務(wù)提供者 
        \Illuminate\Foundation\Bootstrap\BootProviders::class,                    // 注冊(cè)服務(wù)提供者boot
    ];

    // 處理請(qǐng)求
    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);
        }

        $this->app['events']->dispatch(
            new Events\RequestHandled($request, $response)
        );

        return $response;
    }

    protected function sendRequestThroughRouter($request)
    {
        # 一、將$request實(shí)例注冊(cè)到APP容器
        $this->app->instance('request', $request);

        # 二、清除之前的$request實(shí)例緩存
        Facade::clearResolvedInstance('request');

        # 三、啟動(dòng)引導(dǎo)程序
        $this->bootstrap();

        # 四、發(fā)送請(qǐng)求
        return (new Pipeline($this->app)) //創(chuàng)建管道
                    ->send($request)      //發(fā)送請(qǐng)求
                    ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)  //通過(guò)中間件
                    ->then($this->dispatchToRouter());  //分發(fā)到路由
    }

    # 啟動(dòng)引導(dǎo)程序
    public function bootstrap()
    {
        if (! $this->app->hasBeenBootstrapped()) {
            $this->app->bootstrapWith($this->bootstrappers());
        }
    }
    
    # 路由分發(fā)
    protected function dispatchToRouter()
    {
        return function ($request) {
            $this->app->instance('request', $request);

            return $this->router->dispatch($request);
        };
    }

    #  終止程序
    public function terminate($request, $response)
    {
        $this->terminateMiddleware($request, $response);

        $this->app->terminate();
    }

Laravel 服務(wù)容器模塊

簡(jiǎn)介

服務(wù)容器是一個(gè)用于管理類依賴和執(zhí)行依賴注入的強(qiáng)大工具。是整個(gè)框架的核心;

幾乎所有的服務(wù)容器綁定都是在服務(wù)提供者中完成。

框架調(diào)用分析

在框架直接生成服務(wù)容器的只有一處,在bootstrap/app.php,通過(guò)require引用會(huì)返回服務(wù)容器實(shí)例。通過(guò)require引用有兩處,一處是public/index.php,服務(wù)器訪問(wèn)的入口;另一處是tests/CreatesApplication.php,是單元測(cè)試的入口;

如果想在項(xiàng)目各處中調(diào)用,可以調(diào)用$app = Illuminate\Container\Container::getInstance()或者全局幫助函數(shù)app()獲取服務(wù)容器實(shí)例(也就是Illuminate\Foundation/Application實(shí)例);

Illuminate\Foundation/Application是對(duì)Illuminate\Container\Container的又一層封裝;

Application初始化

那么實(shí)例化Illuminate\Foundation/Application時(shí),做了什么呢?

第一步,設(shè)置應(yīng)用的根目錄,并同時(shí)注冊(cè)核心目錄到服務(wù)容器中;核心的目錄有以下

  • path:目錄app的位置

  • path.base:項(xiàng)目根目錄的位置

  • path.lang:目錄resources/lang的位置

  • path.config:目錄config的位置

  • path.public:目錄public的位置

  • path.storage:目錄storage的位置

  • path.database:目錄database的位置

  • path.resources:目錄resources的位置

  • path.bootstrap:目錄bootstrap的位置

第二步,將當(dāng)前Illuminate\Foundation/Application實(shí)例保存到$instance類變量,并同時(shí)綁定到服務(wù)容器作單例綁定,綁定名為appContainer::class;

第三步,順序分別執(zhí)行注冊(cè)Illuminate\Events\EventServiceProviderIlluminate\Log\LogServiceProviderIlluminate\Routing\RoutingServiceProvider三個(gè)服務(wù)提供者;

注冊(cè)服務(wù)提供者的順序如下:

  • 如果類變量$serviceProviders已經(jīng)存在該服務(wù)提供者并且不需要強(qiáng)制重新注冊(cè),則返回服務(wù)提供者實(shí)例$provider;

  • 未注冊(cè)過(guò)當(dāng)前服務(wù)提供者,則繼續(xù)執(zhí)行以下;

  • 如果存在register方法,執(zhí)行服務(wù)提供者的register方法;

  • 將當(dāng)前服務(wù)提供者$provider實(shí)例保存到類變量$serviceProviders數(shù)組中,同時(shí)標(biāo)記類變量$loadedProviders[get_class($provider)]的值為true

  • 判斷類變量$booted是否為true,如果是true,則執(zhí)行服務(wù)提供者的boot方法;(類變量$booted應(yīng)該是標(biāo)志是否所有服務(wù)提供者均注冊(cè),框架是否啟動(dòng))

第四步,注冊(cè)核心類別名;
比如\Illuminate\Foundation\Application::class\Illuminate\Contracts\Container\Container::class起別名為app;

單元測(cè)試Application的bootstrap啟動(dòng)分析

啟動(dòng)代碼很簡(jiǎn)潔,

Route::get('dev', 'Dev@index');

public function index()
{
     // require 初始化分析上面已經(jīng)介紹了
    $app = require base_path('bootstrap/app.php');
    $kernel = $app->make('Illuminate\Contracts\Http\Kernel');
    
    dd($kernel);
}

構(gòu)造函數(shù)主要干了一件事,注冊(cè)一個(gè)booted完成后的回調(diào)函數(shù),函數(shù)執(zhí)行的內(nèi)容為“注冊(cè) Schedule實(shí)例到服務(wù)提供者,同時(shí)加載用戶定義的Schedule任務(wù)清單”;

bootstrap方法的執(zhí)行內(nèi)容如下:

  1. 加載Illuminate/Foundation/Console/Kernel$bootstrappers變量數(shù)組中的類,執(zhí)行它們的bootstrap方法;

  2. protected $bootstrappers = [
        // 加載 .env 文件
        \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
        // 加載 config 目錄下的配置文件
        \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
        // 自定義錯(cuò)誤報(bào)告,錯(cuò)誤處理方法及呈現(xiàn)
        \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
        // 為 config/app.php 中的 aliases 數(shù)組注冊(cè)類別名
        \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
        // 在服務(wù)容器中單例綁定一個(gè) request 對(duì)象,控制臺(tái)命令會(huì)用到
        \Illuminate\Foundation\Bootstrap\SetRequestForConsole::class,
        // 注冊(cè) config\app.php 中的 providers 服務(wù)提供者
        \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
        // 項(xiàng)目啟動(dòng),執(zhí)行每個(gè) ServiceProvider 的 boot 方法,
        \Illuminate\Foundation\Bootstrap\BootProviders::class,
    ];
  3. 加載延遲的服務(wù)提供者;

Http訪問(wèn)Application的bootstrap啟動(dòng)分析

啟動(dòng)入口文件在public\index.php

$app = require_once __DIR__.'/../bootstrap/app.php';

// 實(shí)例化 Illuminate/Foundation/Http/Kernel 對(duì)象
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

// 中間件處理、業(yè)務(wù)邏輯處理
$response = $kernel->handle(
    // 根據(jù) Symfony 的 request 對(duì)象封裝出 Illuminate\Http\Request
    $request = Illuminate\Http\Request::capture() 
);

$response->send();

// 執(zhí)行所有中間件的 terminate 方法,執(zhí)行 Application 中的 terminatingCallbacks 回調(diào)函數(shù)
$kernel->terminate($request, $response);

重要的類變量數(shù)組

aliases數(shù)組

維護(hù) 類與別名 的數(shù)組;鍵名為 類的全限定類名,鍵值為 數(shù)組,每一個(gè)元素都是該類的別名;

判斷指定類是否有別名:app()->isAlias($name);

獲取指定類的別名:app()->getAlias($abstract);

abstractAliases數(shù)組

維護(hù) 類與別名 的數(shù)組;鍵名為 別名,鍵值為 類的全限定類名;

instances數(shù)組

維護(hù) 類與實(shí)例的數(shù)組;鍵名為 類的全限定類名,鍵值為該類的實(shí)例;

移除綁定類:app()->forgetInstance($abstract);

移除所有綁定類:app()->forgetInstances();

bindings數(shù)組

通過(guò) bind 方法實(shí)現(xiàn) 接口類與實(shí)現(xiàn)的綁定;

獲取bindings數(shù)組中的內(nèi)容:app()->getBindings()

resolved數(shù)組

鍵名為 類的全限定類名,鍵值為布爾值類型(true表示已解析過(guò),false表示未解析過(guò));

with 數(shù)組

resolved過(guò)程中,會(huì)有一些參數(shù);with數(shù)組就是參數(shù)棧,開(kāi)始解析時(shí)將參數(shù)入棧,結(jié)束解析時(shí)參數(shù)出棧;

contextual數(shù)組

上下文綁定數(shù)組;第一維數(shù)組鍵名為 場(chǎng)合類(比如某個(gè)Controller類的類名),第二維數(shù)組鍵名為 抽象類(需要實(shí)現(xiàn)的接口類),鍵值為 Closure 或 某個(gè)具體類的類名;

tags數(shù)組

維護(hù) 標(biāo)簽與類 的數(shù)組;鍵名是 標(biāo)簽名,鍵值是 對(duì)應(yīng)要綁定的類的名稱;

如果調(diào)用tagged方法,會(huì)將鍵值數(shù)組中的類都make出來(lái),并以數(shù)組形式返回;

extenders數(shù)組

makeresolve出對(duì)象的時(shí)候,會(huì)執(zhí)行

foreach ($this->getExtenders($abstract) as $extender) {    $object = $extender($object, $this);}

能對(duì)解析出來(lái)的對(duì)象進(jìn)行修飾;

methodBindings數(shù)組

向容器綁定方法與及實(shí)現(xiàn):app()->bindMethod($method, $callback)

判斷容器內(nèi)是否有指定方法的實(shí)現(xiàn):app()->hasMethodBinding($method)
執(zhí)行方法的實(shí)現(xiàn):app()->callMethodBinding($method, $instance)或者app()->call($method)

buildStack數(shù)組

調(diào)用build方法時(shí)維護(hù)的棧,棧中存放的是當(dāng)前要new的類名;

reboundCallbacks數(shù)組

當(dāng)調(diào)用rebound函數(shù)時(shí),會(huì)觸發(fā)rebound中為此$abstract設(shè)置的回調(diào)函數(shù);

注冊(cè)入口:app()->rebinding($abstract, Closure $callback);

serviceProviders數(shù)組

已在系統(tǒng)注冊(cè)的服務(wù)提供者ServiceProvider;

數(shù)組內(nèi)存放的是loadedProviders鍵名對(duì)應(yīng)類的實(shí)例;

loadedProviders數(shù)組

系統(tǒng)已加載的ServiceProvider的集合;鍵名為ServiceProvider的全限定類名,鍵值為布爾值(true表示已加載,false表示未加載);

獲取延遲加載對(duì)象:app()->getLoadedProviders();

deferredServices數(shù)組

有些服務(wù)提供者是會(huì)延遲加載的;這時(shí)候會(huì)將這些服務(wù)提供者聲明的服務(wù)登錄在deferredServices數(shù)組,鍵名為延遲加載對(duì)象名 ,鍵值為該延遲加載對(duì)象所在的ServiceProvider;

獲取延遲加載對(duì)象:app()->getDeferredServices();

bootingCallbacks數(shù)組

項(xiàng)目啟動(dòng)前執(zhí)行的回調(diào)函數(shù);(項(xiàng)目啟動(dòng)是在執(zhí)行\Illuminate\Foundation\Bootstrap\BootProviders::class的時(shí)候)

注冊(cè)入口:app()->booting($callback);

bootedCallbacks數(shù)組

項(xiàng)目啟動(dòng)后執(zhí)行的回調(diào)函數(shù);(項(xiàng)目啟動(dòng)是在執(zhí)行\Illuminate\Foundation\Bootstrap\BootProviders::class的時(shí)候)

注冊(cè)入口:app()->booted($callback);

resolvingCallbacks數(shù)組

解析時(shí)回調(diào)函數(shù)集合;鍵名為 類名, 鍵值為 回調(diào)函數(shù)數(shù)組,每一個(gè)元素都是回調(diào)函數(shù);

注冊(cè)入口:app()->resolving($abstract, $callback);

afterResolvingCallbacks數(shù)組

解析后回調(diào)函數(shù)集合;鍵名為 類名, 鍵值為 回調(diào)函數(shù)數(shù)組,每一個(gè)元素都是回調(diào)函數(shù);

注冊(cè)入口:app()->afterResolving($abstract, $callback);

globalResolvingCallbacks數(shù)組

全局解析時(shí)回調(diào)函數(shù)集合;每一次resolve方法調(diào)用時(shí)都會(huì)執(zhí)行的回調(diào)函數(shù)集合;

注冊(cè)入口:app()->resolving($callback);

globalAfterResolvingCallbacks數(shù)組

全局解析后回調(diào)函數(shù)集合;每一次resolve方法調(diào)用后都會(huì)執(zhí)行的回調(diào)函數(shù)集合;

注冊(cè)入口:app()->afterResolving($callback);

terminatingCallbacks數(shù)組

系統(tǒng)在返回response之后,會(huì)執(zhí)行terminate方法,來(lái)做應(yīng)用結(jié)束前的掃尾處理;

這個(gè)數(shù)組就是執(zhí)行terminate方法時(shí)會(huì)執(zhí)行的回調(diào)函數(shù)集合;

注冊(cè)入口:app()->terminating(Closure $callback);

常用方法的解析

bind方法

public function bind($abstract, $concrete = null, $shared = false)

第一個(gè)參數(shù)是要注冊(cè)的類名或接口名,第二個(gè)參數(shù)是返回類的實(shí)例的閉包(或類的實(shí)例類名),第三個(gè)參數(shù)是否是單例;

方法內(nèi)部流程:

  1. unsetinstancesaliases數(shù)組中鍵值為 $abstract 的元素;

  2. 如果 $concrete 值為 null ,將 $abstract 賦值給 $concrete

  3. 如果 $concrete 不是 Closure 對(duì)象,則封裝成閉包;

  4. $concrete$shared 通過(guò) compact,添加進(jìn) bindings數(shù)組,鍵名為 $abstract;

  5. 判斷 $abstractresolvedinstances數(shù)組中是否存在,如果存在,則執(zhí)行第 6 步;

  6. 觸發(fā) rebound回調(diào)函數(shù);如果 reboundCallbacks 數(shù)組中注冊(cè)以 $abstract 為鍵名的回調(diào)函數(shù),則執(zhí)行這些回調(diào)函數(shù);

涉及數(shù)組:instancesaliases(unset 操作)、bindings(add 操作)

singleton方法

單例綁定;

public function singleton($abstract, $concrete = null)    $this->bind($abstract, $concrete, true);}

涉及數(shù)組:instancesaliases(unset 操作)、bindings(add 操作)

bindIf方法

單例綁定;

public function bindIf($abstract, $concrete = null, $shared = false) {
    if (! $this->bound($abstract)) {
        $this->bind($abstract, $concrete, $shared);
    }
}

涉及數(shù)組:instancesaliases(unset 操作)、bindings(add 操作)

instance方法

綁定實(shí)例;

public function instance($abstract, $instance)

方法內(nèi)部流程:

  1. 如果$abstractaliases數(shù)組中存在,則從abstractAliases中所有的值數(shù)組中移除該類;

  2. unsetaliases 數(shù)組中鍵名為 $abstract的元素;

  3. 賦值操作:$this->instances[$abstract] = $instance;

  4. 判斷 $abstractresolvedinstances數(shù)組中是否存在,如果存在,則執(zhí)行第 5 步;

  5. 觸發(fā) rebound回調(diào)函數(shù);如果 reboundCallbacks 數(shù)組中注冊(cè)以 $abstract 為鍵名的回調(diào)函數(shù),則執(zhí)行這些回調(diào)函數(shù);

涉及數(shù)組:instances(add 操作)、aliasesabstractAliases(unset 操作)

make方法

public function make($abstract) {    return $this->resolve($abstract);}

alias

給類起別名;

public function alias($abstract, $alias) {
    $this->aliases[$alias] = $abstract;
    
    $this->abstractAliases[$abstract][] = $alias;
}

涉及數(shù)組:aliasesabstractAliases(add 操作)

laravel 的源代碼生命周期

第一步 Laravel 應(yīng)用的所有請(qǐng)求入口都是 public/index.php 文件。打開(kāi) index.php 發(fā)現(xiàn)代碼也就幾行。

下面我們來(lái)講一下每一句代碼的作用是什么?

// 定義了laravel一個(gè)請(qǐng)求的開(kāi)始時(shí)間
define('LARAVEL_START', microtime(true));

// composer自動(dòng)加載機(jī)制
require __DIR__.'/../vendor/autoload.php';

// 這句話你就可以理解laravel,在最開(kāi)始引入了一個(gè)ioc容器。
$app = require_once __DIR__.'/../bootstrap/app.php';

// 打開(kāi)__DIR__.'/../bootstrap/app.php';你會(huì)發(fā)現(xiàn)這段代碼,綁定了Illuminate\Contracts\Http\Kernel::class,
// 這個(gè)你可以理解成之前我們所說(shuō)的$ioc->bind();方法。
// $app->singleton(
//     Illuminate\Contracts\Http\Kernel::class,
//    App\Http\Kernel::class
// );

// 這個(gè)相當(dāng)于我們創(chuàng)建了Kernel::class的服務(wù)提供者
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

// 獲取一個(gè) Request ,返回一個(gè) Response。以把該內(nèi)核想象作一個(gè)代表整個(gè)應(yīng)用的大黑盒子,輸入 HTTP 請(qǐng)求,返回 HTTP 響應(yīng)。
$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

// 就是把我們服務(wù)器的結(jié)果返回給瀏覽器。
$response->send(); 

// 這個(gè)就是執(zhí)行我們比較耗時(shí)的請(qǐng)求,
$kernel->terminate($request, $response);

走到這里你會(huì)發(fā)現(xiàn),是不是在我們學(xué)會(huì)了 ioc,服務(wù)提供者理解起來(lái)就比較簡(jiǎn)單了。那 $middleware,服務(wù)提供者都是在哪個(gè)文件注冊(cè)運(yùn)行的呢?

打開(kāi) App\Http\Kernel::class 這個(gè)文件,你會(huì)發(fā)現(xiàn)定義了一堆需要加載的 $middleware。這個(gè) kernel 的主要方法還是在他的父類里面 Illuminate\Foundation\Http\Kernel 中。

打開(kāi) Illuminate\Foundation\Http\Kernel,你會(huì)發(fā)現(xiàn)定義了啟動(dòng)時(shí)需要做的事呢?

protected $bootstrappers = [
    \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
    \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
    \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
    \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
    \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
    \Illuminate\Foundation\Bootstrap\BootProviders::class,
];

$bootstrappers 就定義了我們的 RegisterFacades.class,RegisterProviders.class 這兩個(gè)類的意思就是要將我們?cè)?app.config 中的 Providers,Facades 注入到我們的 Ioc 容器中。

到此,相信大家對(duì)“Laravel的生命周期實(shí)例分析”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!


網(wǎng)站標(biāo)題:Laravel的生命周期實(shí)例分析
分享網(wǎng)址:http://weahome.cn/article/jpodsg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部