1. A_zara

    No comment

    A_zara
Changes in body
Source | HTML | Preview

Laravelのドキュメントにおける概念について調べて見た

前置き

調べたかったから調べました。
この調べはLaravelの日本語ドキュメントにおける流れに沿って制作しています。
今回まとめた結果を図にまとめるとこんな感じ
さ.png

概論 : はじまり

初めの読み込み index.php

全てのリクエストはまずはじめにindex.phpにたどり着く。Laravelにおいて、このindex.phpはフレームワークを読み取る入り口でしかありません。
 index.phpではLaravel等のcomposerでダウンロードしたライブラリなどで生成されたクラス等の定義をしたファイルを読み取ります。

 とありますが、どんな感じで動いているのか気になったので何を読み込んでいるのか見ていきましょう。
まずはじめにindex.phpの中身を見て見ましょう。

public/index.php
<?php

/**
 * Laravel - A PHP Framework For Web Artisans
 *
 * @package  Laravel
 * @author   Taylor Otwell <taylor@laravel.com>
 */

define('LARAVEL_START', microtime(true));

/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader for
| our application. We just need to utilize it! We'll simply require it
| into the script here so that we don't have to worry about manual
| loading any of our classes later on. It feels great to relax.
|
*/

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

/*
|--------------------------------------------------------------------------
| Turn On The Lights
|--------------------------------------------------------------------------
|
| We need to illuminate PHP development, so let us turn on the lights.
| This bootstraps the framework and gets it ready for use, then it
| will load up this application so that we can run it and send
| the responses back to the browser and delight our users.
|
*/

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

/*
|--------------------------------------------------------------------------
| Run The Application
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request
| through the kernel, and send the associated response back to
| the client's browser allowing them to enjoy the creative
| and wonderful application we have prepared for them.
|
*/

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

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

$response->send();

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

index.phpはこのように記載されておりまずはじめにrequire __DIR__.'/../vendor/autoload.php';を読み込んでいます。
この際の読み込みは下記のようになります。

  • ClassLoader.php
    PSR-0PSR-4に準拠して各種クラスを読み込む関数を定義
  • autoload_static.php
    Laravelの基礎になったsymphonyやLaravel自体のクラス読み込みを行なっている。つまりユーザーによって変化を起こさないClassの読み込みを行なっていると思われる
  • autoload_namespaces.php
    下記のものを取得するために利用される。

    を呼び出しています。主にこれらはユニットテストやコンソール装飾、またドクトリンの拡張のために読み込まれていると想定されます。

  • autoload_psr4.php

    読み込んだnamespaceにおける全てのClassをオートロードしていると思われる。

  • autoload_classmap.php

    名前のままcomposerで読み込んだフレームワークやライブラリを全てわかりやすくMap化しています。多分ココを見れば元のファイルを眺めることができる。

  • autoload_files.php

    最後の総仕上げで読み込んだsymphonyなどのフレームワークやライブラリなど最初に読み込むべきファイルを読み込むためのものだと思われる。

次に読み込むのは bootstrap/app.php

その後bootstrap/app.phpファイルを読み取り、Laravelアプリケーションのインスタンスを取得します。
この時Laravelが初めてアクションを起こし、アプリケーション/サービスコンテナのインスタンスを生成します。

とありますが、どんな動きをしているのでしょうか?$app = require_once __DIR__.'/../bootstrap/app.php';

まずはじめにココでは書かれている通りにAPP/サービスコンテナのインスタンスを生成しています。その後Singletonを利用し、HttpやconsoleといったkernelやHandlerをまとめ、このサービスコンテナにおけるリクエストの一元化を行います。
この際Laravelの元となっているSymfonyの基幹部とその拡張を行うLaravelのkernelが処理を行なっているようです。
内部では$middleware,$middlewareGroups,$routeMiddlewareの定義を行なっています。
今回はHTTPカーネルを代表で見ていきましょう。
\$middleware

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,
];

\$middlewareGroups,\$routeMiddleware

これに関してはすごく詳しく書いてあったものがあったのでこちらを参照
一応軽く触れておきます。
Web

  • EncryptCookies :  Cookieの暗号・復号処理
  • AddQueuedCookiesToResponse :  Cookieをレスポンスヘッダに登録
  • StartSession :  Sessionを生成取得処理
  • ShareErrorsFromSession :  Sessionに保存したエラーをViewにセットする
  • VerifyCsrfToken :  CSRFトークンやチェックを行う機能
  • SubstituteBindings :  Route Model Binding を実行する機能

API

  • throttle:60,1 →$routeMiddleware の throttleを参照
  • bindings → $routeMiddleware の bindingsを参照

routeMiddleware

protected $routeMiddleware = [
    'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];
  • auth そのルートでのユーザー認証を必須とする
  • auth.basic そのルートでのBasic認証を必須とする
  • bindings Route Model Binding を実行する
  • cache.headers ヘッダーのキャッシュをセットする
  • can アクションに対してポリシーを付与する
  • guest 認証済かチェックし、認証済であれば /home にリダイレクトする機能
  • signed 署名付きルートのための署名処理
  • throttle 同一ユーザーが単位時間内に規定回数以上のアクセスを行ったかどうかチェックする機能

主にこのbootstrap/app.phpではセキュリティに関するものが多くリクエストの処理を柔軟に行えるのが特徴と思われる。さらにこのカーネルにはhandleメソッドが使われておりすごくシンプルで、Requestを受け取り、Responseをリターンすることから、カーネルをアプリケーション全体を表す大きなブラックボックスだと考えるのが妥当かと思われる。

サービスプロバイダ

サービスプロバイダはデータベース、キュー、バリデーション、ルーティングなど、フレームワークの様々なコンポーネントの初期起動処理に責任をもちます。フレームワークにより提供されている全機能を初期化し、設定するものですから、サービスプロバイダはLaravelの初期処理の過程全体で一番重要な機能です。

 カーネル起動時に読み込まれるconfigは\Illuminate\Foundation\Bootstrap\RegisterProviders::classのBootstrap methodで呼び出されます。

public function registerConfiguredProviders()
{
    $providers = Collection::make($this->config['app.providers'])
                    ->partition(function ($provider) {
                        return Str::startsWith($provider, 'Illuminate\\');
                    });

    $providers->splice(1, 0, [$this->make(PackageManifest::class)->providers()]);

    (new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath()))
                ->load($providers->collapse()->toArray());
}
public function getCachedServicesPath()
{
    return $this->bootstrapPath().'/cache/services.php';
}
public function bootstrapPath($path = '')
{
    return $this->basePath.DIRECTORY_SEPARATOR.'bootstrap'.($path ? DIRECTORY_SEPARATOR.$path : $path);
}

ProviderRepositoryに登録を行い、それをロードしていることがわかります。
この際にキャッシュされたservice.phpをもとにLoadを行うためにLoad内では$providers内部の配列を一度解体し、際配列化しています。

その後、bootを行います。
この際、\Illuminate\Foundation\Bootstrap\BootProviders::classではbootメソッドを呼び出します。
これは、最初の起動の際に読み込まれますが起動済みであればこの動作は行わないで済みます。

リクエストのディスパッチ

アプリケーションの初期処理が済み、全サービスプロバイダが登録されたら、ディスパッチ(実行制御の移行)するためにルーターへRequestが手渡されます。ルーターはそのリクエストをルートかコントローラにディスパッチし、その時にルートに指定されているミドルウェアも実行されます。

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

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

参考
PSR-0について
PSR-4について
Prophecy
Parsedown
Mockery
PHP Console Highlighter
Php Console Color
doctrine
Singleton
メンテナンスモードについて
POSTサイズの確認
文字のトリム
空文字をnullへ置き換え
トラステッドプロキシ統合
middlewaregroupまとめ
laravel.com/api
laravel.com/docs/5.3/middleware
日本語ドキュメント