浜松のWEBシステム開発・スマートフォンアプリ開発・RTK-GNSS関連の開発はお任せください
株式会社シーポイントラボ
TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:静岡県浜松市中区富塚町1933-1 佐鳴湖パークタウンサウス2F

【Laravel】クライアントからのリクエストの値を自動変換する

 Laravel は PHP のフレームワークです。Laravel は同じくPHP のフレームワークである Symfony の機能を多分に使っており、クライアントからのリクエストをいい感じのオブジェクトにする Symfony のコードの一部分を使ってもいます(Symfony は Symfony 自身のコードの断片をコンポーネントと称しており、コンポーネントを個々に使うことを推奨しているためコードの一部分だけを別ライブラリで利用することは Symfony 的にも正しいです)。
 この Symfony のリクエストをいい感じにする機能は HttpFoundation コンポーネントに属しており、Symfony\Component\HttpFoundation\Request クラスにまとまっています。
The HttpFoundation Component (Symfony Docs)
 Laravel を使用したコード上では vendor/symfony/http-foundation/Request.php にこのクラスが書かれています。Laravel では Symfony\Component\HttpFoundation\Request クラスを継承した Illuminate\Http\Request クラス(vendor/laravel/framework/src/Illuminate/Http/Request.php)を作成し、さらにフォームリクエスト等に繋がっていきます。
 Laravel 6.20.7 中での使用例としては web サーバとして動く時のルートである public/index.php とそこから呼び出される vendor/laravel/framework/src/Illuminate/Http/Request.php に次の記述があります。

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

// vendor/laravel/framework/src/Illuminate/Http/Request.php
    /**
     * Create a new Illuminate HTTP request from server variables.
     *
     * @return static
     */
    public static function capture()
    {
        static::enableHttpMethodParameterOverride();
        // Symfony\Component\HttpFoundation\Request のグローバル変数を元にインスタンス化するメソッド createFromGlobals を利用
        return static::createFromBase(SymfonyRequest::createFromGlobals());
    }
    
    /**
     * SymfonyRequest は Symfony\Component\HttpFoundation\Request のエイリアスです。
     * 素のリクエストからフォームリクエスト等のあるリクエストクラスから別のリクエストクラスへの変換はここで行われます。
     * Create an Illuminate request from a Symfony instance.
     *
     * @param  \Symfony\Component\HttpFoundation\Request  $request
     * @return static
     */
    public static function createFromBase(SymfonyRequest $request)
    {
        if ($request instanceof static) {
            return $request;
        }

        $newRequest = (new static)->duplicate(
            $request->query->all(), $request->request->all(), $request->attributes->all(),
            $request->cookies->all(), $request->files->all(), $request->server->all()
        );

        $newRequest->headers->replace($request->headers->all());

        $newRequest->content = $request->content;

        $newRequest->request = $newRequest->getInputSource();

        return $newRequest;
    }

 上記例の様に Laravel のコードは Symfony の機能を破壊せずに使っており(コンストラクタを上書きしたりせずラッピングと機能拡張に留める等)Symfonyの用意した Symfony\Component\HttpFoundation\Request::initialize メソッドの書き換えが機能します。
 initialize メソッドはその名の通り初期化メソッドでリクエストオブジェクトとしてインスタンス化した時など新たにリクエストオブジェクトが作られた時にフレームワーク側で呼び出されます。
The HttpFoundation Component (Symfony Docs)
 また Laravel には dependency injection をコントローラのメソッドで実現する仕組みが備わっており、この仕組みの中でリクエストオブジェクトの変換を行います。
コントローラ 6.x Laravel#メソッドインジェクション
 この二つを利用して次の様にすることでリクエストのパラメータをコントローラ内、フォームリクエストのバリデーション内などで自動的に変換した状態で扱えます。

/** 自作プロジェクトのリクエストクラスの基底クラス */
class BaseRequest extends \Illuminate\Http\Request
{
    /**
     * key => 'true' な文字列で送られてきたPOSTパラメータを true という真偽値に変換する
     * @param array       $query      GET
     * @param array       $request    POST
     * @param array       $attributes
     * @param array       $cookies
     * @param array       $files
     * @param array       $server
     * @param string|null $content
     */
    public function initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): void
    {
        parent::initialize($query, $request, $attributes, $cookies, $files, $server, $content);

        foreach ($this->request as $k => $v) {
            // POST パラメータの変換例
            if ($v === 'true') {
                $this->request->set($k, true);
            }
        }
    }
}
/** コントローラクラス */
class HogeController
{
    public function index(BaseRequest $request)
    {
        $request->is_hoge; // もし is_hoge というキーで 'true' が送られてきてもここでは true として扱える
    }
}

 これを利用すると multipart/form-data を用いた HTTP リクエストの文字列のみ制限などを緩和してプログラムを比較的快適に作れます。

  • この記事いいね! (0)