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