ホームページ > PHPフレームワーク > Laravel > LaravelにおけるHTTPカーネルの詳細な分析

LaravelにおけるHTTPカーネルの詳細な分析

不言
リリース: 2018-11-12 14:15:36
転載
4143 人が閲覧しました

この記事は、Laravel の HTTP コアの詳細な分析を提供します。必要な方は参考にしていただければ幸いです。

Http カーネル

Http カーネルは、Laravel でフレームワークのコアコンポーネントを接続し、## を介してネットワークリクエストを行うために使用されます。 #public/index .php は Http カーネルを使用してフレームワークを開始し、artisan コマンド、スケジュールされたタスク、キュー起動フレームワークなどの他のプロセスはコンソール カーネルを使用します。 out Http カーネルが行うこと。

カーネルバインディング

Http カーネルは、フレームワークのさまざまな部分を接続してネットワークリクエストを処理するために Laravel で使用されるため、カーネルがどのように Laravel のアプリケーションインスタンスにロードされるかを見てみましょう。 public/index.php では、最初にスキャフォールディング ファイル bootstrap/app.php によってアプリケーションが初期化されることがわかります。

以下は bootstrap/app.php のコードで、これには 2 つの主要な部分が含まれています。アプリケーション インスタンスを作成し、カーネルを APP サービス コンテナにバインドします。

<?php
// 第一部分: 创建应用实例
$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.&#39;/../&#39;)
);

// 第二部分: 完成内核绑定
$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;
ログイン後にコピー
HTTP カーネルは、IlluminateFoundationHttpKernel クラスを継承し、HTTP カーネル内でミドルウェア関連の配列を定義します。アプリケーションからの HTTP 応答のリクエストと処理。

<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
    /**
     * The application&#39;s global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\TrustProxies::class,
    ];
    /**
     * The application&#39;s route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        &#39;web&#39; => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];
    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used inpidually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    ];
}
ログイン後にコピー
その親クラス「IlluminateFoundationHttpKernel」では、属性名「bootstrappers」を持つブートストラップ配列が内部的に定義されています:

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,
];
ログイン後にコピー
ブートストラップ グループには、環境検出、構成の読み込み、例外処理の完了が含まれます, ファサードの登録、サービス プロバイダーの登録、サービスの起動が 6 つのブートストラップ手順です。

アプリケーション解析コア

アプリケーションの初期化フェーズ中に Http コアをアプリケーションのサービス コンテナにバインドした後、public/index.php でサービス コンテナの使用を確認できます。 HTTP カーネル インスタンスの出力:

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
ログイン後にコピー
カーネルをインスタンス化すると、HTTP カーネルで定義されたミドルウェアがルーターに登録され、アプリケーション ミドルウェアが実際に処理する前にルートを呼び出すことができます。リクエストをフィルタリングする目的:

namespace Illuminate\Foundation\Http;
...
class Kernel implements KernelContract
{
    /**
     * Create a new HTTP kernel instance.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @param  \Illuminate\Routing\Router  $router
     * @return void
     */
    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);
        }
    }
}

namespace Illuminate/Routing;
class Router implements RegistrarContract, BindingRegistrar
{
    /**
     * Register a group of middleware.
     *
     * @param  string  $name
     * @param  array  $middleware
     * @return $this
     */
    public function middlewareGroup($name, array $middleware)
    {
        $this->middlewareGroups[$name] = $middleware;

        return $this;
    }
    
    /**
     * Register a short-hand name for a middleware.
     *
     * @param  string  $name
     * @param  string  $class
     * @return $this
     */
    public function aliasMiddleware($name, $class)
    {
        $this->middleware[$name] = $class;

        return $this;
    }
}
ログイン後にコピー
HTTP リクエストの処理

サービス解決を通じて HTTP コア インスタンスの作成が完了した後、HTTP コア インスタンスを使用して HTTP リクエストを処理できます

//public/index.php
$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);
ログイン後にコピー
リクエストを処理する前に、Illuminate\Http\Request の Capture() メソッドを通じてアプリケーションに入る HTTP リクエストの情報に基づいて Laravel リクエスト リクエスト インスタンスが作成されます。このリクエスト リクエスト インスタンスは残りの部分で使用されます。これは、この HTTP リクエストの抽象化です。

HTTP リクエストを Laravel リクエスト リクエスト インスタンスに抽象化した後、リクエスト インスタンスは HTTP カーネルのハンドル メソッドに送信され、リクエストの処理は handle メソッドによって完了します。

namespace Illuminate\Foundation\Http;

class Kernel implements KernelContract
{
    /**
     * Handle an incoming HTTP request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    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;
    }
}
ログイン後にコピー
ハンドル メソッドはリクエスト オブジェクトを受け取り、最後にレスポンス オブジェクトを生成します。実際、私たちは多くのモジュールを説明するときに、handle メソッドを出発点として使用して、モジュール内のロジックを徐々に詳しく説明します。その中で、sendRequestThroughRouter メソッドについて説明します。サービス プロバイダーとミドルウェアの両方で、カーネルで定義されたブート プログラムがロードされてアプリケーションが起動され、パイプライン オブジェクトを使用して HTTP リクエスト オブジェクトが送信され、フレームワークで定義された HTTP ミドルウェアとルーティング ミドルウェアを介してフローが実行されます。リクエストをフィルタリングし、最後にリクエストをハンドラー (コントローラー メソッドまたはルート内のクロージャ) に渡し、ハンドラーから返される対応する応答を返します。

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());
}
    
/*引导启动Laravel应用程序
1. DetectEnvironment  检查环境
2. LoadConfiguration  加载应用配置
3. ConfigureLogging   配置日至
4. HandleException    注册异常处理的Handler
5. RegisterFacades    注册Facades 
6. RegisterProviders  注册Providers 
7. BootProviders      启动Providers
*/
public function bootstrap()
{
    if (! $this->app->hasBeenBootstrapped()) {
    /**依次执行$bootstrappers中每一个bootstrapper的bootstrap()函数
        $bootstrappers = [
             'Illuminate\Foundation\Bootstrap\DetectEnvironment',
             'Illuminate\Foundation\Bootstrap\LoadConfiguration',
             'Illuminate\Foundation\Bootstrap\ConfigureLogging',
             'Illuminate\Foundation\Bootstrap\HandleExceptions',
             'Illuminate\Foundation\Bootstrap\RegisterFacades',
             'Illuminate\Foundation\Bootstrap\RegisterProviders',
             'Illuminate\Foundation\Bootstrap\BootProviders',
            ];*/
            $this->app->bootstrapWith($this->bootstrappers());
    }
}
ログイン後にコピー
応答の送信

上記の段階を経て、最終的に応答が返されるようになりました。次のステップは応答を送信することです。

//public/index.php
$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

// 发送响应
$response->send();
ログイン後にコピー
レスポンスの送信は、親クラス

Symfony で定義されている Illuminate\Http\Response 親クラスの send() メソッドによって完了します。 \Component\HttpFoundation\Response 真ん中。

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;
}
ログイン後にコピー
Response オブジェクトの詳細な分析については、Laravel Response オブジェクトについて説明した前の章を参照してください。

アプリケーションを終了する

応答が送信された後、HTTP カーネルは

terminableミドルウェアを呼び出して後続の処理を実行します。たとえば、Laravel の組み込み「セッション」ミドルウェアは、応答がブラウザーに送信された後、セッション データをメモリに書き込みます。

// public/index.php
// 终止程序
$kernel->terminate($request, $response);
ログイン後にコピー
//Illuminate\Foundation\Http\Kernel
public function terminate($request, $response)
{
    $this->terminateMiddleware($request, $response);
    $this->app->terminate();
}

// 终止中间件
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, $parameters) = $this->parseMiddleware($middleware);
        $instance = $this->app->make($name);
        if (method_exists($instance, 'terminate')) {
            $instance->terminate($request, $response);
        }
    }
}
ログイン後にコピー
HTTP カーネルの

terminate メソッドは、呼び出しが完了すると、terminable ミドルウェアの terminate メソッドを呼び出します。 HTTP リクエストが受信され、レスポンスが返されます。アプリケーションのライフサイクルが終了しました。

概要

このセクションで紹介する HTTP カーネルは、主にアプリケーションの初期化、アプリケーションの誘導、HTTP リクエストの Request オブジェクトへの抽象化、および Request オブジェクトの中間通過を行うように設計されています。ファイル到着ハンドラーは応答を生成し、その応答はクライアントに送信されます。

以上がLaravelにおけるHTTPカーネルの詳細な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:segmentfault.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート