HTTPレスポンス
レスポンスの生成
文字列と配列
すべてのルートとコントローラは、ユーザーのブラウザに送り返すレスポンスを返さなければなりません。Laravelは、レスポンスを返すためのさまざまな方法を提供しています。最も基本的なレスポンスは、ルートまたはコントローラから文字列を返すことです。フレームワークは自動的にその文字列を完全なHTTPレスポンスに変換します。
1Route::get('/', function () {2 return 'Hello World';3});
ルートやコントローラから文字列を返すだけでなく、配列を返すこともできます。フレームワークは、その配列を自動的にJSONレスポンスに変換します。
1Route::get('/', function () {2 return [1, 2, 3];3});
ルートやコントローラからEloquentコレクションも返せることを知っていましたか?自動的にJSONに変換されます。ぜひ試してください!
レスポンスオブジェクト
通常、ルートアクションから単純な文字列や配列を返すだけではありません。代わりに、完全なIlluminate\Http\Responseインスタンスやビューを返すことになります。
完全なResponseインスタンスを返すと、レスポンスのHTTPステータスコードとヘッダをカスタマイズできます。ResponseインスタンスはSymfony\Component\HttpFoundation\Responseクラスを継承しており、HTTPレスポンスを構築するためのさまざまなメソッドを提供しています。
1Route::get('/home', function () {2 return response('Hello World', 200)3 ->header('Content-Type', 'text/plain');4});
Eloquentモデルとコレクション
ルートやコントローラからEloquent ORMモデルやコレクションを直接返すこともできます。その場合、Laravelはモデルの非表示属性を尊重しながら、モデルとコレクションを自動的にJSONレスポンスへ変換します。
1use App\Models\User;2 3Route::get('/user/{user}', function (User $user) {4 return $user;5});
レスポンスへのヘッダ付加
ほとんどのレスポンスメソッドはチェーン可能であり、レスポンスインスタンスを流暢に構築できることを覚えておいてください。たとえば、headerメソッドを使用して、ユーザーにレスポンスを送り返す前に、一連のヘッダをレスポンスに追加できます。
1return response($content)2 ->header('Content-Type', $type)3 ->header('X-Header-One', 'Header Value')4 ->header('X-Header-Two', 'Header Value');
あるいは、withHeadersメソッドを使用して、レスポンスに追加するヘッダの配列を指定できます。
1return response($content)2 ->withHeaders([3 'Content-Type' => $type,4 'X-Header-One' => 'Header Value',5 'X-Header-Two' => 'Header Value',6 ]);
キャッシュ制御ミドルウェア
Laravelにはcache.headersミドルウェアが含まれており、ルートのグループに対してCache-Controlヘッダを素早く設定するために使用できます。ディレクティブは、対応するキャッシュ制御ディレクティブの「スネークケース」を使用して指定し、セミコロンで区切る必要があります。ディレクティブのリストにetagが指定されている場合、レスポンスコンテンツのMD5ハッシュが自動的にETag識別子として設定されます。
1Route::middleware('cache.headers:public;max_age=2628000;etag')->group(function () {2 Route::get('/privacy', function () {3 // ...4 });5 6 Route::get('/terms', function () {7 // ...8 });9});
レスポンスへのクッキー付加
送信するIlluminate\Http\Responseインスタンスにクッキーを添付するには、cookieメソッドを使用します。このメソッドには、名前、値、およびクッキーが有効と見なされる分数を渡してください。
1return response('Hello World')->cookie(2 'name', 'value', $minutes3);
cookieメソッドは、あまり頻繁に使用されない引数もいくつか受け入れます。一般的に、これらの引数はPHPネイティブのsetcookieメソッドに渡す引数と同じ目的と意味を持っています。
1return response('Hello World')->cookie(2 'name', 'value', $minutes, $path, $domain, $secure, $httpOnly3);
送信レスポンスでクッキーが送信されるようにしたいが、そのレスポンスのインスタンスがまだない場合は、Cookieファサードを使用して、レスポンスが送信されるときに添付されるようにクッキーを「キュー」へ登録できます。queueメソッドは、クッキーインスタンスの作成に必要な引数を受け入れます。これらのクッキーは、ブラウザに送信される前に送信レスポンスに添付されます。
1use Illuminate\Support\Facades\Cookie;2 3Cookie::queue('name', 'value', $minutes);
クッキーインスタンスの生成
後でレスポンスインスタンスに添付できるSymfony\Component\HttpFoundation\Cookieインスタンスを生成したい場合は、グローバルなcookieヘルパが使用できます。このクッキーは、レスポンスインスタンスに添付されない限り、クライアントに送り返されることはありません。
1$cookie = cookie('name', 'value', $minutes);2 3return response('Hello World')->cookie($cookie);
クッキーを早期に期限切れにする
送信レスポンスのwithoutCookieメソッドを介してクッキーを期限切れにすることで、クッキーを削除できます。
1return response('Hello World')->withoutCookie('name');
送信レスポンスのインスタンスがまだない場合は、Cookieファサードのexpireメソッドを使用してクッキーを期限切れにできます。
1Cookie::expire('name');
クッキーと暗号化
デフォルトで、Laravelが生成するすべてのクッキーはIlluminate\Cookie\Middleware\EncryptCookiesミドルウェアのおかげで暗号化および署名されており、クライアントによる変更や読み取りができません。アプリケーションで生成されるクッキーの一部に対して暗号化を無効にしたい場合は、アプリケーションのbootstrap/app.phpファイルでencryptCookiesメソッドを使用できます。
1->withMiddleware(function (Middleware $middleware) {2 $middleware->encryptCookies(except: [3 'cookie_name',4 ]);5})
リダイレクト
リダイレクトレスポンスはIlluminate\Http\RedirectResponseクラスのインスタンスであり、ユーザーを別のURLにリダイレクトするために必要な適切なヘッダを含んでいます。RedirectResponseインスタンスを生成するには、いくつかの方法があります。最も簡単な方法は、グローバルなredirectヘルパを使用することです。
1Route::get('/dashboard', function () {2 return redirect('/home/dashboard');3});
送信されたフォームが無効な場合など、ユーザーを以前の場所へリダイレクトしたい場合があります。これは、グローバルなbackヘルパ関数を使用して行います。この機能はセッションを利用するため、back関数を呼び出すルートがwebミドルウェアグループを使用していることを確認してください。
1Route::post('/user/profile', function () {2 // Validate the request...3 4 return back()->withInput();5});
名前付きルートへのリダイレクト
redirectヘルパをパラメータなしで呼び出すと、Illuminate\Routing\Redirectorのインスタンスが返され、Redirectorインスタンスのどのメソッドも呼び出すことができます。たとえば、名前付きルートへのRedirectResponseを生成するには、routeメソッドを使用します。
1return redirect()->route('login');
ルートにパラメータがある場合は、routeメソッドの第2引数として渡すことができます。
1// For a route with the following URI: /profile/{id}2 3return redirect()->route('profile', ['id' => 1]);
Eloquentモデルによるパラメータのデータ入力
Eloquentモデルからデータを入力する「ID」パラメータを持つルートにリダイレクトする場合は、モデル自体を渡すことができます。IDは自動的に抽出されます。
1// For a route with the following URI: /profile/{id}2 3return redirect()->route('profile', [$user]);
ルートパラメータに配置される値をカスタマイズしたい場合は、ルートパラメータ定義(/profile/{id:slug})でカラムを指定するか、EloquentモデルのgetRouteKeyメソッドをオーバーライドできます。
1/**2 * Get the value of the model's route key.3 */4public function getRouteKey(): mixed5{6 return $this->slug;7}
コントローラアクションへのリダイレクト
コントローラアクションへのリダイレクトも生成できます。これを行うには、コントローラとアクション名をactionメソッドに渡します。
1use App\Http\Controllers\UserController;2 3return redirect()->action([UserController::class, 'index']);
コントローラルートがパラメータを必要とする場合は、actionメソッドの第2引数として渡すことができます。
1return redirect()->action(2 [UserController::class, 'profile'], ['id' => 1]3);
外部ドメインへのリダイレクト
アプリケーション外のドメインにリダイレクトする必要がある場合があります。これを行うには、awayメソッドを呼び出します。これにより、追加のURLエンコーディング、検証、または確認なしでRedirectResponseが作成されます。
1return redirect()->away('https://www.google.com');
フラッシュセッションデータ付きリダイレクト
新しいURLへのリダイレクトとセッションへのデータのフラッシュは、通常、同時に行われます。典型的には、アクションが正常に実行された後、成功メッセージをセッションにフラッシュするときに行われます。便利なことに、RedirectResponseインスタンスを作成し、単一の流暢なメソッドチェーンでセッションにデータをフラッシュできます。
1Route::post('/user/profile', function () {2 // ...3 4 return redirect('/dashboard')->with('status', 'Profile updated!');5});
ユーザーがリダイレクトされた後、セッションからフラッシュされたメッセージを表示できます。たとえば、Blade構文を使用します。
1@if (session('status'))2 <div class="alert alert-success">3 {{ session('status') }}4 </div>5@endif
入力値付きリダイレクト
RedirectResponseインスタンスが提供するwithInputメソッドを使用して、ユーザーを新しい場所にリダイレクトする前に、現在のリクエストの入力データをセッションにフラッシュできます。これは通常、ユーザーが検証エラーに遭遇した場合に行われます。入力がセッションにフラッシュされると、次のリクエストで簡単にそれを取得してフォームに再入力できます。
1return back()->withInput();
その他のレスポンスタイプ
responseヘルパは、他のタイプのレスポンスインスタンスを生成するために使用できます。responseヘルパを引数なしで呼び出すと、Illuminate\Contracts\Routing\ResponseFactory 契約の実装が返されます。この契約は、レスポンスを生成するためのいくつかの便利なメソッドを提供します。
Viewレスポンス
レスポンスのステータスとヘッダを制御する必要があるが、レスポンスのコンテンツとしてビューを返す必要がある場合は、viewメソッドを使用する必要があります。
1return response()2 ->view('hello', $data, 200)3 ->header('Content-Type', $type);
もちろん、カスタムHTTPステータスコードやカスタムヘッダを渡す必要がない場合は、グローバルなviewヘルパ関数を使用できます。
JSONレスポンス
jsonメソッドは、Content-Typeヘッダを自動的にapplication/jsonに設定し、指定された配列をjson_encode PHP関数を使用してJSONに変換します。
1return response()->json([2 'name' => 'Abigail',3 'state' => 'CA',4]);
JSONPレスポンスを作成したい場合は、jsonメソッドとwithCallbackメソッドを組み合わせて使用できます。
1return response()2 ->json(['name' => 'Abigail', 'state' => 'CA'])3 ->withCallback($request->input('callback'));
ファイルダウンロード
downloadメソッドは、ユーザーのブラウザに指定されたパスのファイルをダウンロードさせるレスポンスを生成するために使用できます。downloadメソッドは、メソッドの第2引数としてファイル名を受け入れます。これにより、ファイルをダウンロードするユーザーに表示されるファイル名が決まります。最後に、メソッドの第3引数としてHTTPヘッダの配列を渡すことができます。
1return response()->download($pathToFile);2 3return response()->download($pathToFile, $name, $headers);
ファイルダウンロードを管理するSymfony HttpFoundationでは、ダウンロードするファイル名がASCIIファイル名である必要があります。
ファイルレスポンス
fileメソッドは、画像やPDFなどのファイルをダウンロードを開始するのではなく、ユーザーのブラウザに直接表示するために使用できます。このメソッドは、最初の引数としてファイルの絶対パスを、第2引数としてヘッダの配列を受け入れます。
1return response()->file($pathToFile);2 3return response()->file($pathToFile, $headers);
ストリームレスポンス
データが生成されるときにクライアントにストリーミングすることで、特に非常に大きなレスポンスの場合、メモリ使用量を大幅に削減し、パフォーマンスを向上させることができます。ストリームレスポンスを使用すると、サーバがデータの送信を完了する前に、クライアントがデータの処理を開始できます。
1function streamedContent(): Generator { 2 yield 'Hello, '; 3 yield 'World!'; 4} 5 6Route::get('/stream', function () { 7 return response()->stream(function (): void { 8 foreach (streamedContent() as $chunk) { 9 echo $chunk;10 ob_flush();11 flush();12 sleep(2); // Simulate delay between chunks...13 }14 }, 200, ['X-Accel-Buffering' => 'no']);15});
内部的に、LaravelはPHPの出力バッファリング機能を利用しています。上の例でわかるように、バッファリングされたコンテンツをクライアントにプッシュするには、ob_flush関数とflush関数を使用する必要があります。
ストリームJSONレスポンス
JSONデータを段階的にストリーミングする必要がある場合は、streamJsonメソッドを利用できます。このメソッドは、JavaScriptで簡単に解析できる形式で、大規模なデータセットをブラウザに段階的に送信する必要がある場合に特に役立ちます。
1use App\Models\User;2 3Route::get('/users.json', function () {4 return response()->streamJson([5 'users' => User::cursor(),6 ]);7});
ストリームダウンロード
特定の操作の文字列レスポンスを、操作のコンテンツをディスクに書き込むことなく、ダウンロード可能なレスポンスに変換したい場合があります。このようなシナリオでは、streamDownloadメソッドを使用できます。このメソッドは、コールバック、ファイル名、およびオプションのヘッダ配列を引数として受け入れます。
1use App\Services\GitHub;2 3return response()->streamDownload(function () {4 echo GitHub::api('repo')5 ->contents()6 ->readme('laravel', 'laravel')['contents'];7}, 'laravel-readme.md');
レスポンスマクロ
さまざまなルートやコントローラで再利用できるカスタムレスポンスを定義したい場合は、Responseファサードのmacroメソッドを使用できます。通常、このメソッドは、アプリケーションのサービスプロバイダの1つ、たとえばApp\Providers\AppServiceProviderサービスプロバイダのbootメソッドから呼び出す必要があります。
1<?php 2 3namespace App\Providers; 4 5use Illuminate\Support\Facades\Response; 6use Illuminate\Support\ServiceProvider; 7 8class AppServiceProvider extends ServiceProvider 9{10 /**11 * Bootstrap any application services.12 */13 public function boot(): void14 {15 Response::macro('caps', function (string $value) {16 return Response::make(strtoupper($value));17 });18 }19}
macro関数は、最初の引数として名前を、第2引数としてクロージャを受け入れます。マクロのクロージャは、ResponseFactory実装またはresponseヘルパからマクロ名を呼び出すときに実行されます。
1return response()->caps('foo');