Laravel学習メモ：Request

## HTTPリクエスト

## 参考
[https://readouble.com/laravel/10.x/ja/requests.html](https://readouble.com/laravel/10.x/ja/requests.html)

- Laravelの`Illuminate\Http\Request`クラス
    - アプリケーションが処理している現在のHTTPリクエストを操作
    - リクエストとともに送信される入力、クッキー、およびファイルを取得するオブジェクト指向の手段を提供
- リクエストの操作
    - リクエストへのアクセス
        - DIを使って現在のHTTPリクエストのインスタンスを取得するには
        - ルートクロージャかコントローラメソッドで`Illuminate\Http\Request`をタイプヒントする。
            
            ```php
            // 以下のことを説明している
            public function store(Request $request): RedirectResponse
            {
            ```
            
    - 依存注入とルートパラメータ
        - コントローラメソッドがルートパラメータからの入力も期待している場合は他の依存関係の後にルートパラメータをリストする必要がある
        - idとかを渡すという意味
        
        ```php
        use App\Http\Controllers\UserController;
        
        Route::put('/user/{id}', [UserController::class, 'update']);
        ```
        
        ```php
        <?php
        
        namespace App\Http\Controllers;
        
        use Illuminate\Http\RedirectResponse;
        use Illuminate\Http\Request;
        
        class UserController extends Controller
        {
            /**
             * 指定ユーザーを更新
             */
            public function update(Request $request, string $id): RedirectResponse
            {
                // ユーザーの更新処理…
        
                return redirect('/users');
            }
        }
        ```
        
- 重要なメソッド
    - リクエストパスの取得
        
        ```php
        $uri = $request->path();
        ```
        
    - リクエストパス/ルートの検査
        
        ```php
        // ワイルドカード
        if ($request->is('admin/*')) {
            // ...
        }
        
        // 名前付きルートに一致するか
        if ($request->routeIs('admin.*')) {
            // ...
        }
        ```
        
    - リクエストURLの取得
        
        ```php
        // クエリ文字無し
        $url = $request->url();
        // クエリ文字列あり
        $urlWithQueryString = $request->fullUrl();
        
        // クエリ文字列にデータを追加する
        $request->fullUrlWithQuery(['type' => 'phone']);
        ```
        
    - リクエストヘッダ
        
        ```php
        $value = $request->header('X-Header-Name');
        
        $value = $request->header('X-Header-Name', 'default');
        
        // Bearerトークン
        $token = $request->bearerToken();
        ```
        
    - リクエストIPアドレス
        
        ```php
        $ipAddress = $request->ip();
        ```
        
- Inputの取得
    - 全入力データの取得
        
        ```php
        // 配列として取得
        $input = $request->all();
        
        // コレクションとして取り出す
        $input = $request->collect();
        ```
        
    - 単一のデータの取得
        
        ```php
        $name = $request->input('name');
        
        // すべてを連想配列でほしかったら
        $input = $request->input();
        ```
        
    - クエリ文字列の取得
        
        ```php
        $input = $request->input();
        $name = $request->query('name', 'Helen');
        $query = $request->query();
        ```
        
- JSONの取得
    - リクエストの`Content-Type`ヘッダが`application/json`に設定されていたらinputメソッドで取得可能。
    - ドットを利用してネストした値をとれる
    
    ```php
    $name = $request->input('user.name');
    ```
    
- Enum入力値の取得
    - 以下の場合にnullを返す
        - リクエストに指定した名前の入力値が含まれていない場合
        - 入力値にマッチするenumバッキング値をそのenumが持たない場合
    - enumメソッドは入力値の名前とenumクラスを第一引数、第二引数にとる
    
    ```php
    use App\Enums\Status;
    
    $status = $request->enum('status', Status::class);
    ```
    
- 入力の存在の判定
    - hasメソッド
        
        ```php
        // nameに値が存在するか？
        if ($request->has('name')) {
            // ...
        }
        
        // すべてが存在するか？
        if ($request->has(['name', 'email'])) {
            // ...
        }
        ```
        
- 追加入力のマージ
    - mergeメソッド
        - 既存の入力データに追加の入力を自分でマージする。
        
        ```php
        $request->merge(['votes' => 0]);
        ```
        
    - mergeIfMissingメソッド
        
        ```php
        // なければ追加する
        $request->mergeIfMissing(['votes' => 0]);
        ```
        
- セッションへの入力の一時保持
    - `flash`メソッド
        - セッションに現在の入力情報を一時保持する。
            
            ```php
            $request->flush();
            ```
            
    - `flashOnly`メソッドと`flashExcept`メソッド
        
        ```php
        // 配列で指定した値をセッションへ一時保存
        $request->flashOnly(['username', 'email']);
        
        // パスワードを除外
        $request->flashExcept('password');
        ```
        
    - 一時保存した入力の取得: oldメソッド
        
        ```php
        $username = $request->old('username');
        ```
        
        - oldヘルパもある。Bladeで呼び出すこともある
- クッキーの取得
    
    ```php
    $value = $request->cookie('name');
    ```
    
- 入力のトリムと正規化
    - デフォルトで、Laravelはミドルウェアに以下が登録されている。
        - `App\Http\Middleware\TrimStrings`
        - `Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull`
    - App/Http/Kernelクラスで登録されている。
    - 文字列を自動的にトリミングし、空の文字列フィールドを`null`に変換する
    - 無効化したかったら。。。。
        - すべてのリクエストに対して
            - Kernelから２つのミドルウェアを削除
        - 一部のリクエストに対して
            - `skipWhen`メソッドを使用
            - アプリケーションの`AppServiceProvider`の`boot`メソッドで呼び出します。
- ファイル
    - アップロード済みファイルの取得
        
        ```php
        $file = $request->file('photo');
        
        $file = $request->photo;
        ```
        
    - ファイルが存在するか判定
        
        ```php
        if ($request->hasFile('photo')) {
            // ...
        }
        ```
        
    - その他メソッド
        
        ```php
        // バリデーション
        if ($request->file('photo')->isValid()) {
            // ...
        }
        
        // ファイルパスを取得
        $path = $request->photo->path();
        // 拡張子の取得
        $extension = $request->photo->extension();
        
        // 設定済みファイルシステムへ登録
        $path = $request->photo->store('images');
        // 保存先を第２引数で指定
        $path = $request->photo->store('images', 's3');
        
        // ファイル名を指定する場合
        $path = $request->photo->storeAs('images', 'filename.jpg');
        ```
        
- 信頼するプロキシの設定
    - `url`ヘルパを使用するとアプリケーションがHTTPSリンクを生成しないことがある
        - TLS/SSL証明書を末端とするロードバランサーの背後でアプリケーションを実行している場合
            - アプリケーションがポート80でロードバランサーからトラフィックを転送していて、安全なリンクを生成する必要があることを認識していないため。
        - `App\Http\Middleware\TrustProxies`ミドルウェアを使用する
            
            ```php
            <?php
            
            namespace App\Http\Middleware;
            
            use Illuminate\Http\Middleware\TrustProxies as Middleware;
            use Illuminate\Http\Request;
            
            class TrustProxies extends Middleware
            {
                /**
                 * このアプリケーションで信頼するプロキシ
                 *
                 * @var string|array
                 */
                protected $proxies = [
                    '192.168.1.1',
                    '192.168.1.2',
                ];
            
                /**
                 * プロキシを検出するために使用すべきヘッダ
                 *
                 * @var int
                 */
                protected $headers = Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO;
            }
            ```
            
        - すべてのプロキシを信頼する場合。（AWSなどのロードバランサを使用するケース）
            - `protected $proxies = '*';`
- 信頼するホストの設定
    - Laravelに特定のホスト名にしか応答しないように指示する必要がある場合は、アプリケーションのミドルウェアである`App\Http\Middleware\TrustHosts`を有効にすることで可能
        
        ```php
        /**
         * 信頼できるホストパターンの取得
         *
         * @return array<int, string>
         */
        public function hosts(): array
        {
            return [
                'laravel.test',
                $this->allSubdomainsOfApplicationUrl(),
            ];
        }
        ```