国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Laravel 啟動(dòng)流程

VPointer / 3333人閱讀

摘要:年月日階段劃分請(qǐng)求到響應(yīng)的整個(gè)執(zhí)行階段歸納為個(gè)程序啟動(dòng)準(zhǔn)備階段文件自動(dòng)加載服務(wù)容器實(shí)例化基礎(chǔ)服務(wù)提供者的注冊(cè)核心類的實(shí)例化請(qǐng)求實(shí)例化階段實(shí)例化實(shí)例請(qǐng)求處理階段準(zhǔn)備請(qǐng)求處理的環(huán)境將請(qǐng)求實(shí)例通過中間件處理及通過路由和控制器的分發(fā)控制響應(yīng)發(fā)送和

Last-Modified: 2019年5月10日16:19:07

階段劃分
Laravel 5.5
請(qǐng)求到響應(yīng)的整個(gè)執(zhí)行階段歸納為 4 個(gè):

程序啟動(dòng)準(zhǔn)備階段

文件自動(dòng)加載

服務(wù)容器實(shí)例化

基礎(chǔ)服務(wù)提供者的注冊(cè)

核心類的實(shí)例化

請(qǐng)求實(shí)例化階段

實(shí)例化 Request 實(shí)例

請(qǐng)求處理階段

準(zhǔn)備請(qǐng)求處理的環(huán)境

將請(qǐng)求實(shí)例通過中間件處理 及 通過路由和控制器的分發(fā)控制

響應(yīng)發(fā)送和程序終止階段

將響應(yīng)內(nèi)容返回給客戶端

記錄與客戶端有關(guān)的信息等

1. 程序啟動(dòng)準(zhǔn)備

程序入口在 index.php

require __DIR__."/../vendor/autoload.php";

$app = require_once __DIR__."/../bootstrap/app.php";    # 獲取服務(wù)容器實(shí)例

$kernel = $app->make(IlluminateContractsHttpKernel::class);

$response = $kernel->handle(
    $request = IlluminateHttpRequest::capture()
);

$response->send();

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

創(chuàng)建服務(wù)容器實(shí)例

服務(wù)容器的創(chuàng)建在 bootstrapapp.php 中進(jìn)行.

$app = new IlluminateFoundationApplication(
    realpath(__DIR__."/../")
);
1.1 容器基礎(chǔ)配置

容器 Application 的構(gòu)造函數(shù):

public function __construct($basePath = null)
{
    if ($basePath) {
        $this->setBasePath($basePath);
    }

    $this->registerBaseBindings();

    $this->registerBaseServiceProviders();

    $this->registerCoreContainerAliases();
}

構(gòu)造函數(shù) 主要完成以下基本配置:

目錄路徑(綁定到容器中, 并提供類方法獲取子目錄)

public function setBasePath($basePath)
{
    $this->basePath = rtrim($basePath, "/");

    $this->bindPathsInContainer();

    return $this;
}

protected function bindPathsInContainer()
    {
        $this->instance("path", $this->path());
        $this->instance("path.base", $this->basePath());
        $this->instance("path.lang", $this->langPath());
        $this->instance("path.config", $this->configPath());
        $this->instance("path.public", $this->publicPath());
        $this->instance("path.storage", $this->storagePath());
        $this->instance("path.database", $this->databasePath());
        $this->instance("path.resources", $this->resourcePath());
        $this->instance("path.bootstrap", $this->bootstrapPath());
    }

綁定容器自身

protected function registerBaseBindings()
{
    static::setInstance($this);

    $this->instance("app", $this);

    $this->instance(Container::class, $this);

    $this->instance(PackageManifest::class, new PackageManifest(
        new Filesystem, $this->basePath(), $this->getCachedPackagesPath()
    ));
}

基礎(chǔ)服務(wù)注冊(cè)( Event, Log, Route)

protected function registerBaseServiceProviders()
{
    $this->register(new EventServiceProvider($this));

    $this->register(new LogServiceProvider($this));

    $this->register(new RoutingServiceProvider($this));
}

別名注冊(cè)

多個(gè)接口名 對(duì)應(yīng)一個(gè)簡短別名, 后續(xù)在注冊(cè)服務(wù)時(shí)只需綁定到別名上即可 (而不必綁定到具體接口名)

public function registerCoreContainerAliases()
{
    foreach ([
        "app"                  => [IlluminateFoundationApplication::class, IlluminateContractsContainerContainer::class, IlluminateContractsFoundationApplication::class,  PsrContainerContainerInterface::class],
        "auth"                 => [IlluminateAuthAuthManager::class, IlluminateContractsAuthFactory::class],
        "auth.driver"          => [IlluminateContractsAuthGuard::class],
        "blade.compiler"       => [IlluminateViewCompilersBladeCompiler::class],
        "cache"                => [IlluminateCacheCacheManager::class, IlluminateContractsCacheFactory::class],
        "cache.store"          => [IlluminateCacheRepository::class, IlluminateContractsCacheRepository::class],
        "config"               => [IlluminateConfigRepository::class, IlluminateContractsConfigRepository::class],
        "cookie"               => [IlluminateCookieCookieJar::class, IlluminateContractsCookieFactory::class, IlluminateContractsCookieQueueingFactory::class],
        "encrypter"            => [IlluminateEncryptionEncrypter::class, IlluminateContractsEncryptionEncrypter::class],
        "db"                   => [IlluminateDatabaseDatabaseManager::class],
        "db.connection"        => [IlluminateDatabaseConnection::class, IlluminateDatabaseConnectionInterface::class],
        "events"               => [IlluminateEventsDispatcher::class, IlluminateContractsEventsDispatcher::class],
        "files"                => [IlluminateFilesystemFilesystem::class],
        "filesystem"           => [IlluminateFilesystemFilesystemManager::class, IlluminateContractsFilesystemFactory::class],
        "filesystem.disk"      => [IlluminateContractsFilesystemFilesystem::class],
        "filesystem.cloud"     => [IlluminateContractsFilesystemCloud::class],
        "hash"                 => [IlluminateContractsHashingHasher::class],
        "translator"           => [IlluminateTranslationTranslator::class, IlluminateContractsTranslationTranslator::class],
        "log"                  => [IlluminateLogWriter::class, IlluminateContractsLoggingLog::class, PsrLogLoggerInterface::class],
        "mailer"               => [IlluminateMailMailer::class, IlluminateContractsMailMailer::class, IlluminateContractsMailMailQueue::class],
        "auth.password"        => [IlluminateAuthPasswordsPasswordBrokerManager::class, IlluminateContractsAuthPasswordBrokerFactory::class],
        "auth.password.broker" => [IlluminateAuthPasswordsPasswordBroker::class, IlluminateContractsAuthPasswordBroker::class],
        "queue"                => [IlluminateQueueQueueManager::class, IlluminateContractsQueueFactory::class, IlluminateContractsQueueMonitor::class],
        "queue.connection"     => [IlluminateContractsQueueQueue::class],
        "queue.failer"         => [IlluminateQueueFailedFailedJobProviderInterface::class],
        "redirect"             => [IlluminateRoutingRedirector::class],
        "redis"                => [IlluminateRedisRedisManager::class, IlluminateContractsRedisFactory::class],
        "request"              => [IlluminateHttpRequest::class, SymfonyComponentHttpFoundationRequest::class],
        "router"               => [IlluminateRoutingRouter::class, IlluminateContractsRoutingRegistrar::class, IlluminateContractsRoutingBindingRegistrar::class],
        "session"              => [IlluminateSessionSessionManager::class],
        "session.store"        => [IlluminateSessionStore::class, IlluminateContractsSessionSession::class],
        "url"                  => [IlluminateRoutingUrlGenerator::class, IlluminateContractsRoutingUrlGenerator::class],
        "validator"            => [IlluminateValidationFactory::class, IlluminateContractsValidationFactory::class],
        "view"                 => [IlluminateViewFactory::class, IlluminateContractsViewFactory::class],
    ] as $key => $aliases) {
        foreach ($aliases as $alias) {
            $this->alias($key, $alias);
        }
    }
}

1.2 核心類綁定
$app->singleton(
    IlluminateContractsHttpKernel::class,
    AppHttpKernel::class
);

$app->singleton(
    IlluminateContractsConsoleKernel::class,
    AppConsoleKernel::class
);

$app->singleton(
    IlluminateContractsDebugExceptionHandler::class,
    AppExceptionsHandler::class
);

綁定重要接口:

Http 核心類

命令行 核心類

異常處理類

1.3 實(shí)例化 Http 核心類
$kernel = $app->make(IlluminateContractsHttpKernel::class);

Http 核心類的構(gòu)造函數(shù)

public function __construct(Application $app, Router $router)
{
    $this->app = $app;
    $this->router = $router;

    $router->middlewarePriority = $this->middlewarePriority;

    foreach ($this->middlewareGroups as $key => $middleware) {
        $router->middlewareGroup($key, $middleware);
    }

    foreach ($this->routeMiddleware as $key => $middleware) {
        $router->aliasMiddleware($key, $middleware);
    }
}

上述過程主要做的事是將中間件賦值給路由

中間件順序優(yōu)先級(jí)列表

中間件組

中間件別名

核心類 app/Http/Kernel.php

 [
            // Cookie 加密解密
            AppHttpMiddlewareEncryptCookies::class,

            // 將 Cookie 添加到響應(yīng)中
            IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class,

            // 開啟會(huì)話
            IlluminateSessionMiddlewareStartSession::class,

            // 認(rèn)證用戶,此中間件以后 Auth 類才能生效
            // 見:https://d.laravel-china.org/docs/5.5/authentication
            IlluminateSessionMiddlewareAuthenticateSession::class,

            // 將系統(tǒng)的錯(cuò)誤數(shù)據(jù)注入到視圖變量 $errors 中
            IlluminateViewMiddlewareShareErrorsFromSession::class,

            // 檢驗(yàn) CSRF ,防止跨站請(qǐng)求偽造的安全威脅
            // 見:https://d.laravel-china.org/docs/5.5/csrf
            AppHttpMiddlewareVerifyCsrfToken::class,

            // 處理路由綁定
            // 見:https://d.laravel-china.org/docs/5.5/routing#route-model-binding
            IlluminateRoutingMiddlewareSubstituteBindings::class,
        ],

        // API 中間件組,應(yīng)用于 routes/api.php 路由文件
        "api" => [
            // 使用別名來調(diào)用中間件
            // 請(qǐng)見:https://d.laravel-china.org/docs/5.5/middleware#為路由分配中間件
            "throttle:60,1",
            "bindings",
        ],
    ];

    // 中間件別名設(shè)置,允許你使用別名調(diào)用中間件,例如上面的 api 中間件組調(diào)用
    protected $routeMiddleware = [

        // 只有登錄用戶才能訪問,我們?cè)诳刂破鞯臉?gòu)造方法中大量使用
        "auth" => IlluminateAuthMiddlewareAuthenticate::class,

        // HTTP Basic Auth 認(rèn)證
        "auth.basic" => IlluminateAuthMiddlewareAuthenticateWithBasicAuth::class,

        // 處理路由綁定
        // 見:https://d.laravel-china.org/docs/5.5/routing#route-model-binding
        "bindings" => IlluminateRoutingMiddlewareSubstituteBindings::class,

        // 用戶授權(quán)功能
        "can" => IlluminateAuthMiddlewareAuthorize::class,

        // 只有游客才能訪問,在 register 和 login 請(qǐng)求中使用,只有未登錄用戶才能訪問這些頁面
        "guest" => AppHttpMiddlewareRedirectIfAuthenticated::class,

        // 訪問節(jié)流,類似于 『1 分鐘只能請(qǐng)求 10 次』的需求,一般在 API 中使用
        "throttle" => IlluminateRoutingMiddlewareThrottleRequests::class,
    ];
}
2. 請(qǐng)求實(shí)例化
以處理 Http 請(qǐng)求為例

index.php 入口文件

$response = $kernel->handle(
    $request = IlluminateHttpRequest::capture()
);

請(qǐng)求是通過 IlluminateHttpRequest::capture() 實(shí)例化的, 主要是將請(qǐng)求信息以對(duì)象形式表現(xiàn)出來

3. 請(qǐng)求處理

入口文件:

$response = $kernel->handle(
    $request = IlluminateHttpRequest::capture()
);

$kernel->handle(...) 處理請(qǐng)求過程

IlluminateFoundationHttpKernel
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 EventsRequestHandled($request, $response)
    );

    return $response;
}


protected function sendRequestThroughRouter($request)
{
    $this->app->instance("request", $request);

    Facade::clearResolvedInstance("request");

    $this->bootstrap();        # 核心類初始化

    return (new Pipeline($this->app))
        ->send($request)
        ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
        ->then($this->dispatchToRouter());
}


protected function dispatchToRouter()
{
    return function ($request) {
        $this->app->instance("request", $request);

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

實(shí)際處理請(qǐng)求邏輯主要在 sendRequestThroughRouter 方法中, 它主要做了:

核心類的初始化

經(jīng)由中間件過濾后將請(qǐng)求最終交由 Router 處理

對(duì)于 Http 請(qǐng)求處理, 中間件包括:

protected $middleware = [

    IlluminateFoundationHttpMiddlewareCheckForMaintenanceMode::class,

    IlluminateFoundationHttpMiddlewareValidatePostSize::class,

    AppHttpMiddlewareTrimStrings::class,

    IlluminateFoundationHttpMiddlewareConvertEmptyStringsToNull::class,

    AppHttpMiddlewareTrustProxies::class,

];

該中間件數(shù)組定義在 Http 核心類中, 同時(shí)在核心類的構(gòu)造函數(shù)中傳遞給 Router

3.1 請(qǐng)求處理環(huán)境初始化

核心類的初始化 bootstrap()

protected $bootstrappers = [
    IlluminateFoundationBootstrapLoadEnvironmentVariables::class,
    IlluminateFoundationBootstrapLoadConfiguration::class,
    IlluminateFoundationBootstrapHandleExceptions::class,
    IlluminateFoundationBootstrapRegisterFacades::class,
    IlluminateFoundationBootstrapRegisterProviders::class,
    IlluminateFoundationBootstrapBootProviders::class,
];

# 初始化
public function bootstrap()
{
    if (! $this->app->hasBeenBootstrapped()) {
        $this->app->bootstrapWith($this->bootstrappers());
    }
}

protected function bootstrappers()
{
    return $this->bootstrappers;
}

在服務(wù)容器 Application 類中

public function bootstrapWith(array $bootstrappers)
{
    $this->hasBeenBootstrapped = true;

    foreach ($bootstrappers as $bootstrapper) {
        $this["events"]->fire("bootstrapping: ".$bootstrapper, [$this]);

        $this->make($bootstrapper)->bootstrap($this);

        $this["events"]->fire("bootstrapped: ".$bootstrapper, [$this]);
    }
}

該步驟主要是主要是對(duì)核心類中定義的 $bootstrappers 數(shù)組元素(引導(dǎo)類)初始化.

bootstrap 過程具體是在服務(wù)容器來中進(jìn)行, 由核心類調(diào)用并傳入待初始化的類

Http 核心類默認(rèn)包含以下 6 個(gè)啟動(dòng)服務(wù):

1. 環(huán)境監(jiān)測(cè) IlluminateFoundationBootstrapLoadEnvironmentVariables::class

.env 文件中解析環(huán)境變量到 getevn(), $_ENV, $_SERVER

依賴 vlucas/phpdotenv 擴(kuò)展包
2. 配置加載 IlluminateFoundationBootstrapLoadConfiguration::class

載入 config 目錄下所有 php 配置文件, 并將生成的配置存儲(chǔ)類綁定到服務(wù)容器 $app["config"]

同時(shí)配置時(shí)區(qū)及 多字節(jié)格式(utf8)

3. 常處理 IlluminateFoundationBootstrapHandleExceptions::class

報(bào)告所有錯(cuò)誤 error_report(E_ALL)

提供對(duì)未捕獲的異常, 錯(cuò)誤的全局處理 set_error_handler, set_exception_handler, register_shutdown_function

4. 外觀注冊(cè) IlluminateFoundationBootstrapRegisterFacades::class

app.aliases 中讀取外觀配置數(shù)組

"aliases" => [

        "App" => IlluminateSupportFacadesApp::class,
        "Artisan" => IlluminateSupportFacadesArtisan::class,
        "Auth" => IlluminateSupportFacadesAuth::class,
        "Blade" => IlluminateSupportFacadesBlade::class,
        "Broadcast" => IlluminateSupportFacadesBroadcast::class,
        "Bus" => IlluminateSupportFacadesBus::class,
        "Cache" => IlluminateSupportFacadesCache::class,
        "Config" => IlluminateSupportFacadesConfig::class,
        "Cookie" => IlluminateSupportFacadesCookie::class,
        "Crypt" => IlluminateSupportFacadesCrypt::class,
        "DB" => IlluminateSupportFacadesDB::class,
        "Eloquent" => IlluminateDatabaseEloquentModel::class,
        "Event" => IlluminateSupportFacadesEvent::class,
        "File" => IlluminateSupportFacadesFile::class,
        "Gate" => IlluminateSupportFacadesGate::class,
        "Hash" => IlluminateSupportFacadesHash::class,
        "Lang" => IlluminateSupportFacadesLang::class,
        "Log" => IlluminateSupportFacadesLog::class,
        "Mail" => IlluminateSupportFacadesMail::class,
        "Notification" => IlluminateSupportFacadesNotification::class,
        "Password" => IlluminateSupportFacadesPassword::class,
        "Queue" => IlluminateSupportFacadesQueue::class,
        "Redirect" => IlluminateSupportFacadesRedirect::class,
        "Redis" => IlluminateSupportFacadesRedis::class,
        "Request" => IlluminateSupportFacadesRequest::class,
        "Response" => IlluminateSupportFacadesResponse::class,
        "Route" => IlluminateSupportFacadesRoute::class,
        "Schema" => IlluminateSupportFacadesSchema::class,
        "Session" => IlluminateSupportFacadesSession::class,
        "Storage" => IlluminateSupportFacadesStorage::class,
        "URL" => IlluminateSupportFacadesURL::class,
        "Validator" => IlluminateSupportFacadesValidator::class,
        "View" => IlluminateSupportFacadesView::class,

    ],

使用 spl_autoload_register(...) 處理類加載, 配合 class_alias() 提供類的別名調(diào)用

Facade 外觀類基類依賴 __callStatic` 調(diào)用方法( 使用服務(wù)容器實(shí)例化對(duì)應(yīng)類)

5. 服務(wù)提供者注冊(cè) IlluminateFoundationBootstrapRegisterProviders::class

app.providers 中讀取所有服務(wù)提供者

"providers" => [

        /*
         * Laravel Framework Service Providers...
         */
        IlluminateAuthAuthServiceProvider::class,
        IlluminateBroadcastingBroadcastServiceProvider::class,
        IlluminateBusBusServiceProvider::class,
        IlluminateCacheCacheServiceProvider::class,
        IlluminateFoundationProvidersConsoleSupportServiceProvider::class,
        IlluminateCookieCookieServiceProvider::class,
        IlluminateDatabaseDatabaseServiceProvider::class,
        IlluminateEncryptionEncryptionServiceProvider::class,
        IlluminateFilesystemFilesystemServiceProvider::class,
        IlluminateFoundationProvidersFoundationServiceProvider::class,
        IlluminateHashingHashServiceProvider::class,
        IlluminateMailMailServiceProvider::class,
        IlluminateNotificationsNotificationServiceProvider::class,
        IlluminatePaginationPaginationServiceProvider::class,
        IlluminatePipelinePipelineServiceProvider::class,
        IlluminateQueueQueueServiceProvider::class,
        IlluminateRedisRedisServiceProvider::class,
        IlluminateAuthPasswordsPasswordResetServiceProvider::class,
        IlluminateSessionSessionServiceProvider::class,
        IlluminateTranslationTranslationServiceProvider::class,
        IlluminateValidationValidationServiceProvider::class,
        IlluminateViewViewServiceProvider::class,

        /*
         * Package Service Providers...
         */

        /*
         * Application Service Providers...
         */
        AppProvidersAppServiceProvider::class,
        AppProvidersAuthServiceProvider::class,
        // AppProvidersBroadcastServiceProvider::class,
        AppProvidersEventServiceProvider::class,
        AppProvidersRouteServiceProvider::class,    # 路由表生成
    ],

服務(wù)提供者經(jīng)過解析后分為 3 種類型的服務(wù)提供者:

eager 類型

馬上調(diào)用 register 注冊(cè)

deferred 類型

記錄下來, 當(dāng)服務(wù)容器解析對(duì)應(yīng)服務(wù)時(shí), 才注冊(cè)對(duì)應(yīng)的服務(wù)提供者

when 類型

記錄下來, 當(dāng)對(duì)應(yīng) event 觸發(fā)時(shí)在注冊(cè)對(duì)應(yīng)服務(wù)提供者

6. 啟動(dòng)提供者 IlluminateFoundationBootstrapBootProviders::class

調(diào)用服務(wù)容器的 boot() 方法, 依次調(diào)用在服務(wù)容器中 register 的所有服務(wù)提供者的 boot() 方法

3.2 路由處理請(qǐng)求

在內(nèi)核處理請(qǐng)求, 將請(qǐng)求實(shí)例通過中間件處理后, 將請(qǐng)求的處理交給路由 Router 進(jìn)行控制器的分發(fā).

Http Kernel
protected function dispatchToRouter()
{
    return function ($request) {
        $this->app->instance("request", $request);

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

路由表存儲(chǔ)結(jié)構(gòu)說明

IlluminateRoutingRoute 存儲(chǔ)單條路由

IlluminateRoutingRouteCollection 保存所有 Route 實(shí)例, 形成路由表

IlluminateRoutingRouter 類實(shí)例持有 RouteCollection 路由表實(shí)例.

即, 一個(gè) Router 持有一個(gè) RouteCollection, 而 RouteCollection 擁有 N 個(gè) Route

Router 中對(duì)請(qǐng)求的處理同樣經(jīng)過一系列的 路由中間件

# 路由處理請(qǐng)求的入庫
public function dispatchToRoute(Request $request)
{
    return $this->runRoute($request, $this->findRoute($request));
}

# 根據(jù)請(qǐng)求的 url 和 method 查找對(duì)應(yīng)的 route
protected function findRoute($request)
{
    $this->current = $route = $this->routes->match($request);

    $this->container->instance(Route::class, $route);

    return $route;
}

# 根據(jù)對(duì)應(yīng)的請(qǐng)求和路由條目, 返回相應(yīng)的 $response
protected function runRoute(Request $request, Route $route)
{
    $request->setRouteResolver(function () use ($route) {
        return $route;
    });

    $this->events->dispatch(new EventsRouteMatched($route, $request));

    return $this->prepareResponse($request,
                                  $this->runRouteWithinStack($route, $request)
                                 );
}

# 請(qǐng)求經(jīng)過路由中間件過濾后, 交由 route 的 run() 方法處理
protected function runRouteWithinStack(Route $route, Request $request)
{
    $shouldSkipMiddleware = $this->container->bound("middleware.disable") &&
        $this->container->make("middleware.disable") === true;

    $middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddleware($route);

    return (new Pipeline($this->container))
        ->send($request)
        ->through($middleware)
        ->then(function ($request) use ($route) {
            return $this->prepareResponse(
                $request, $route->run()
            );
        });
}

routerun() 方法最終將請(qǐng)求轉(zhuǎn)給 IlluminateRoutingControllerDispatcher::dispatch 處理

public function dispatch(Route $route, $controller, $method)
{
    $parameters = $this->resolveClassMethodDependencies(
        $route->parametersWithoutNulls(), $controller, $method
    );

    if (method_exists($controller, "callAction")) {
            return $controller->callAction($method, $parameters);
    }

    return $controller->{$method}(...array_values($parameters));
}

剩下的事情就是 Controller控制器 的事了.

3.3 處理返回的 Response

Router 中有一個(gè)方法, 用于對(duì)返回的 $response 進(jìn)行處理

public function prepareResponse($request, $response)
{
    return static::toResponse($request, $response);
}

/**
* @return IlluminateHttpResponse|IlluminateHttpJsonResponse
*/
public static function toResponse($request, $response)
{
    if ($response instanceof Responsable) {
        $response = $response->toResponse($request);
    }

    if ($response instanceof PsrResponseInterface) {
        $response = (new HttpFoundationFactory)->createResponse($response);
    } elseif (! $response instanceof SymfonyResponse &&
              ($response instanceof Arrayable ||
               $response instanceof Jsonable ||
               $response instanceof ArrayObject ||
               $response instanceof JsonSerializable ||
               is_array($response))) {
        $response = new JsonResponse($response);
    } elseif (! $response instanceof SymfonyResponse) {
        $response = new Response($response);
    }

    if ($response->getStatusCode() === Response::HTTP_NOT_MODIFIED) {
        $response->setNotModified();
    }

    return $response->prepare($request);    # 最后的處理
}  

上述過程中, 在返回 $response 之前進(jìn)行了最后的處理 $response->prepare($request)

該過程是在 SymfonyComponentHttpFoundationResponse::prepare() 中進(jìn)行

對(duì)響應(yīng)的封裝是通過 IlluminateHttpResponse 類完成, 該類底層是 Symfony 框架的 Response 類

即, SymfonyComponentHttpFoundationResponse

public function prepare(Request $request)
{
    $headers = $this->headers;

    if ($this->isInformational() || $this->isEmpty()) {
        $this->setContent(null);
        $headers->remove("Content-Type");
        $headers->remove("Content-Length");
    } else {
        // Content-type based on the Request
        if (!$headers->has("Content-Type")) {
            $format = $request->getRequestFormat();
            if (null !== $format && $mimeType = $request->getMimeType($format)) {
                $headers->set("Content-Type", $mimeType);
            }
        }

        // Fix Content-Type
        $charset = $this->charset ?: "UTF-8";
        if (!$headers->has("Content-Type")) {
            $headers->set("Content-Type", "text/html; charset=".$charset);
        } elseif (0 === stripos($headers->get("Content-Type"), "text/") && false === stripos($headers->get("Content-Type"), "charset")) {
            // add the charset
            $headers->set("Content-Type", $headers->get("Content-Type")."; charset=".$charset);
        }

        // Fix Content-Length
        if ($headers->has("Transfer-Encoding")) {
            $headers->remove("Content-Length");
        }

        if ($request->isMethod("HEAD")) {
            // cf. RFC2616 14.13
            $length = $headers->get("Content-Length");
            $this->setContent(null);
            if ($length) {
                $headers->set("Content-Length", $length);
            }
        }
    }

    // Fix protocol
    if ("HTTP/1.0" != $request->server->get("SERVER_PROTOCOL")) {
        $this->setProtocolVersion("1.1");
    }

    // Check if we need to send extra expire info headers
    if ("1.0" == $this->getProtocolVersion() && false !== strpos($this->headers->get("Cache-Control"), "no-cache")) {
        $this->headers->set("pragma", "no-cache");
        $this->headers->set("expires", -1);
    }

    $this->ensureIEOverSSLCompatibility($request);

    return $this;
}
4. 響應(yīng)發(fā)送和程序終止 4.1 響應(yīng)的發(fā)送

index.php 入口文件的最后是將響應(yīng)返回給客戶端

$response->send();

SymfonyComponentHttpFoundationResponse

public function send()
{
    $this->sendHeaders();
    $this->sendContent();

    if (function_exists("fastcgi_finish_request")) {
        fastcgi_finish_request();
    } elseif (!in_array(PHP_SAPI, array("cli", "phpdbg"), true)) {
        static::closeOutputBuffers(0, true);
    }

    return $this;
}

public function sendHeaders()
{
    // headers have already been sent by the developer
    if (headers_sent()) {
        return $this;
    }

    // headers
    foreach ($this->headers->allPreserveCase() as $name => $values) {
        foreach ($values as $value) {
            header($name.": ".$value, false, $this->statusCode);
        }
    }

    // status
    header(sprintf("HTTP/%s %s %s", $this->version, $this->statusCode, $this->statusText), true, $this->statusCode);

    return $this;
}

public function sendContent()
{
    echo $this->content;

    return $this;
}
4.2 請(qǐng)求中止

index.php 入口文件的最后:

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

依舊以 Http Kernel 為例:

public function terminate($request, $response)
{
    $this->terminateMiddleware($request, $response);    # 中間件中止處理

    $this->app->terminate();    # 服務(wù)容器的中止處理函數(shù)
}

protected function terminateMiddleware($request, $response)
{
    $middlewares = $this->app->shouldSkipMiddleware() ? [] : array_merge(
        $this->gatherRouteMiddleware($request),
        $this->middleware
    );

    foreach ($middlewares as $middleware) {
        if (! is_string($middleware)) {
            continue;
        }

        list($name) = $this->parseMiddleware($middleware);

        $instance = $this->app->make($name);

        if (method_exists($instance, "terminate")) {
            $instance->terminate($request, $response);
        }
    }
}

此處的中間件指的是定義在 Kernel 中的 $middleware 中間件數(shù)組列表, 不包含 路由中間件.

Laravel 5.1 注: 默認(rèn)只有會(huì)話中間件包含 terminate() 函數(shù)

Application 服務(wù)容器的中止處理函數(shù)

public function terminate()
{
    foreach ($this->terminatingCallbacks as $terminating) {
        $this->call($terminating);
    }
}

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/31436.html

相關(guān)文章

  • Laravel 5 系列教程二:路由,視圖,控制器工作流程

    摘要:但是不用擔(dān)心,我們后續(xù)的教程會(huì)陸續(xù)講解相關(guān)的內(nèi)容。所以上面的路由注冊(cè)其實(shí)就是負(fù)責(zé)解決訪問的時(shí)候的響應(yīng)。 原文來自:https://jellybool.com/post/programming-with-laravel-5-routers-views-controllers-workflow 免費(fèi)視頻教程地址 https://laravist.com/series/laravel-5-b...

    awesome23 評(píng)論0 收藏0
  • Laravel中間件原理

    摘要:直到所有中間件都執(zhí)行完畢,最后在執(zhí)行最后的即上述的方法如果上述有地方難懂的,可以參考這邊文章內(nèi)置函數(shù)在中的使用以上是在通過全局中間件時(shí)的大致流程,通過中間件和路由中間件也是一樣的,都是采用管道流操作,詳情可翻閱源碼 簡介 Laravel 中間件提供了一種方便的機(jī)制來過濾進(jìn)入應(yīng)用的 HTTP 請(qǐng)求, 如ValidatePostSize用來驗(yàn)證POST請(qǐng)求體大小、ThrottleReque...

    張憲坤 評(píng)論0 收藏0
  • Laravel 教程 - 實(shí)戰(zhàn) iBrand 開源電商 API 系統(tǒng)

    摘要:最佳實(shí)踐良好的編碼規(guī)范單元測(cè)試持續(xù)集成文檔,從一開始就形成良好的編碼習(xí)慣。真實(shí)的電商業(yè)務(wù)所有的業(yè)務(wù)需求來自真實(shí)的客戶,并且線上良好運(yùn)營中。 重要通知: Laravel + 小程序的開源電商版本源碼已經(jīng)在 github 上拉,歡迎提交 issue 和 star :) 開源電商 Server 端: Laravel API源碼 開源電商 client 端:小程序源碼 iBrand 簡介...

    iOS122 評(píng)論0 收藏0
  • elastic學(xué)習(xí)筆記

    摘要:至于其他的算一般我習(xí)慣說樹形模型,這里說的概率模型可能是差不多的意思。 要點(diǎn) 不同工具之間版本匹配很重要由點(diǎn)及面,先實(shí)踐起來再學(xué)細(xì)節(jié)的原理和使用 技術(shù)棧 laravel5.5框架+scout組件+elasticsearch6.3.0搜索引擎 輔助 elasticsearch-head 查看集群數(shù)據(jù)可視化 中文分詞插件Ik 介紹 laravel是一款現(xiàn)代化的php框架es是搜索引擎e...

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

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

0條評(píng)論

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