応答の作成

文字列と配列

すべてのルートとコントローラーは、ユーザーのブラウザに返される応答を返す必要があります。Laravelは、応答を返すためのいくつかの異なる方法を提供しています。最も基本的な応答は、ルートまたはコントローラーから文字列を返すことです。フレームワークは、文字列を自動的に完全なHTTP応答に変換します:

  1. Route::get('/', function () {
  2. return 'Hello World';
  3. });

ルートやコントローラーから文字列を返すことに加えて、配列を返すこともできます。フレームワークは、配列を自動的にJSON応答に変換します:

  1. Route::get('/', function () {
  2. return [1, 2, 3];
  3. });

ルートやコントローラーからEloquentコレクションを返すこともできることをご存知ですか?それらは自動的にJSONに変換されます。試してみてください!

応答オブジェクト

通常、ルートアクションから単純な文字列や配列を返すことはありません。代わりに、完全なIlluminate\Http\Responseインスタンスまたはビューを返します。

完全なResponseインスタンスを返すことで、応答のHTTPステータスコードやヘッダーをカスタマイズできます。ResponseインスタンスはSymfony\Component\HttpFoundation\Responseクラスから継承されており、HTTP応答を構築するためのさまざまなメソッドを提供します:

  1. Route::get('/home', function () {
  2. return response('Hello World', 200)
  3. ->header('Content-Type', 'text/plain');
  4. });

Eloquentモデルとコレクション

ルートやコントローラーからEloquent ORMモデルやコレクションを直接返すこともできます。そうすると、LaravelはモデルやコレクションをJSON応答に自動的に変換し、モデルの隠し属性を尊重します:

  1. use App\Models\User;
  2. Route::get('/user/{user}', function (User $user) {
  3. return $user;
  4. });

応答にヘッダーを追加する

ほとんどの応答メソッドはチェーン可能であり、応答インスタンスの流暢な構築を可能にします。たとえば、headerメソッドを使用して、応答をユーザーに返す前に一連のヘッダーを追加できます:

  1. return response($content)
  2. ->header('Content-Type', $type)
  3. ->header('X-Header-One', 'Header Value')
  4. ->header('X-Header-Two', 'Header Value');

または、withHeadersメソッドを使用して、応答に追加するヘッダーの配列を指定できます:

  1. return 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識別子として設定されます:

  1. Route::middleware('cache.headers:public;max_age=2628000;etag')->group(function () {
  2. Route::get('/privacy', function () {
  3. // ...
  4. });
  5. Route::get('/terms', function () {
  6. // ...
  7. });
  8. });

応答にクッキーを追加する

  1. ``````php
  2. return response('Hello World')->cookie(
  3. 'name', 'value', $minutes
  4. );
  5. `
  1. ``````php
  2. return response('Hello World')->cookie(
  3. 'name', 'value', $minutes, $path, $domain, $secure, $httpOnly
  4. );
  5. `

応答とともにクッキーが送信されることを確認したいが、その応答のインスタンスがまだない場合は、Cookieファサードを使用して、応答が送信されるときにクッキーを「キュー」に追加できます。queueメソッドは、クッキーインスタンスを作成するために必要な引数を受け入れます。これらのクッキーは、ブラウザに送信される前に、送信される応答に追加されます:

  1. use Illuminate\Support\Facades\Cookie;
  2. Cookie::queue('name', 'value', $minutes);

クッキーインスタンスの生成

後で応答インスタンスに追加できるSymfony\Component\HttpFoundation\Cookieインスタンスを生成したい場合は、グローバルcookieヘルパーを使用できます。このクッキーは、応答インスタンスに追加されない限り、クライアントに送信されません:

  1. $cookie = cookie('name', 'value', $minutes);
  2. return response('Hello World')->cookie($cookie);

クッキーの早期期限切れ

  1. ``````php
  2. return response('Hello World')->withoutCookie('name');
  3. `

送信中の応答のインスタンスがまだない場合は、Cookieファサードのexpireメソッドを使用してクッキーを期限切れにすることができます:

  1. Cookie::expire('name');

クッキーと暗号化

デフォルトでは、Illuminate\Cookie\Middleware\EncryptCookiesミドルウェアのおかげで、Laravelによって生成されたすべてのクッキーは暗号化され、署名されているため、クライアントによって変更されたり読み取られたりすることはできません。アプリケーションによって生成されたクッキーのサブセットに対して暗号化を無効にしたい場合は、アプリケーションのbootstrap/app.phpファイルでencryptCookiesメソッドを使用できます:

  1. ->withMiddleware(function (Middleware $middleware) {
  2. $middleware->encryptCookies(except: [
  3. 'cookie_name',
  4. ]);
  5. })

リダイレクト

リダイレクト応答はIlluminate\Http\RedirectResponseクラスのインスタンスであり、ユーザーを別のURLにリダイレクトするために必要な適切なヘッダーを含んでいます。RedirectResponseインスタンスを生成する方法はいくつかあります。最も簡単な方法は、グローバルredirectヘルパーを使用することです:

  1. Route::get('/dashboard', function () {
  2. return redirect('/home/dashboard');
  3. });

時には、送信されたフォームが無効な場合など、ユーザーを以前の場所にリダイレクトしたいことがあります。その場合は、グローバルbackヘルパー関数を使用できます。この機能はセッションを利用しているため、back関数を呼び出すルートがwebミドルウェアグループを使用していることを確認してください:

  1. Route::post('/user/profile', function () {
  2. // Validate the request...
  3. return back()->withInput();
  4. });

名前付きルートへのリダイレクト

引数なしでredirectヘルパーを呼び出すと、Illuminate\Routing\Redirectorのインスタンスが返され、Redirectorインスタンスの任意のメソッドを呼び出すことができます。たとえば、名前付きルートへのRedirectResponseを生成するには、routeメソッドを使用できます:

  1. return redirect()->route('login');

ルートにパラメータがある場合は、routeメソッドの2番目の引数としてそれらを渡すことができます:

  1. // For a route with the following URI: /profile/{id}
  2. return redirect()->route('profile', ['id' => 1]);

Eloquentモデルを介したパラメータの埋め込み

Eloquentモデルから埋め込まれている「ID」パラメータを持つルートにリダイレクトしている場合は、モデル自体を渡すことができます。IDは自動的に抽出されます:

  1. // For a route with the following URI: /profile/{id}
  2. return redirect()->route('profile', [$user]);

ルートパラメータに配置される値をカスタマイズしたい場合は、ルートパラメータ定義(/profile/{id:slug})でカラムを指定するか、EloquentモデルのgetRouteKeyメソッドをオーバーライドできます:

  1. /**
  2. * Get the value of the model's route key.
  3. */
  4. public function getRouteKey(): mixed
  5. {
  6. return $this->slug;
  7. }

コントローラーアクションへのリダイレクト

コントローラーアクションへのリダイレクトを生成することもできます。そうするには、actionメソッドにコントローラーとアクション名を渡します:

  1. use App\Http\Controllers\UserController;
  2. return redirect()->action([UserController::class, 'index']);

コントローラーのルートにパラメータが必要な場合は、actionメソッドの2番目の引数としてそれらを渡すことができます:

  1. return redirect()->action(
  2. [UserController::class, 'profile'], ['id' => 1]
  3. );

外部ドメインへのリダイレクト

時には、アプリケーションの外部のドメインにリダイレクトする必要がある場合があります。その場合は、awayメソッドを呼び出すことで、追加のURLエンコーディング、検証、または確認なしにRedirectResponseを作成できます:

  1. return redirect()->away('https://www.google.com');

フラッシュされたセッションデータでのリダイレクト

新しいURLにリダイレクトし、セッションにデータをフラッシュすることは通常同時に行われます。通常、これはアクションを正常に実行した後に行われ、成功メッセージをセッションにフラッシュします。便利なことに、RedirectResponseインスタンスを作成し、単一の流暢なメソッドチェーンでセッションにデータをフラッシュできます:

  1. Route::post('/user/profile', function () {
  2. // ...
  3. return redirect('/dashboard')->with('status', 'Profile updated!');
  4. });

ユーザーがリダイレクトされた後、セッションからフラッシュされたメッセージを表示できます。たとえば、Blade構文を使用して:

  1. @if (session('status'))
  2. <div class="alert alert-success">
  3. {{ session('status') }}
  4. </div>
  5. @endif

入力を使用したリダイレクト

ユーザーを新しい場所にリダイレクトする前に、withInputメソッドを使用して現在のリクエストの入力データをセッションにフラッシュできます。これは通常、ユーザーがバリデーションエラーに遭遇した場合に行われます。入力がセッションにフラッシュされた後、次のリクエスト中に簡単に取得してフォームを再入力できます:

  1. return back()->withInput();

その他の応答タイプ

responseヘルパーを使用して、他のタイプの応答インスタンスを生成できます。引数なしでresponseヘルパーを呼び出すと、Illuminate\Contracts\Routing\ResponseFactory 契約の実装が返されます。この契約は、応答を生成するためのいくつかの便利なメソッドを提供します。

ビュー応答

応答のステータスとヘッダーを制御する必要があるが、応答のコンテンツとしてビューを返す必要がある場合は、viewメソッドを使用する必要があります:

  1. return response()
  2. ->view('hello', $data, 200)
  3. ->header('Content-Type', $type);

もちろん、カスタムHTTPステータスコードやカスタムヘッダーを渡す必要がない場合は、グローバルviewヘルパー関数を使用できます。

JSON応答

jsonメソッドは、Content-Typeヘッダーをapplication/jsonに自動的に設定し、与えられた配列をjson_encode PHP関数を使用してJSONに変換します:

  1. return response()->json([
  2. 'name' => 'Abigail',
  3. 'state' => 'CA',
  4. ]);

JSONP応答を作成したい場合は、jsonメソッドをwithCallbackメソッドと組み合わせて使用できます:

  1. return response()
  2. ->json(['name' => 'Abigail', 'state' => 'CA'])
  3. ->withCallback($request->input('callback'));

ファイルダウンロード

  1. ``````php
  2. return response()->download($pathToFile);
  3. return response()->download($pathToFile, $name, $headers);
  4. `

ファイルダウンロードを管理するSymfony HttpFoundationは、ダウンロードされるファイルがASCIIファイル名を持つことを要求します。

ファイル応答

  1. ``````php
  2. return response()->file($pathToFile);
  3. return response()->file($pathToFile, $headers);
  4. `

ストリーミング応答

生成されるデータをクライアントにストリーミングすることで、メモリ使用量を大幅に削減し、特に非常に大きな応答の場合にパフォーマンスを向上させることができます。ストリーミング応答により、サーバーがデータの送信を完了する前に、クライアントがデータの処理を開始できます:

  1. function streamedContent(): Generator {
  2. yield 'Hello, ';
  3. yield 'World!';
  4. }
  5. Route::get('/stream', function () {
  6. return response()->stream(function (): void {
  7. foreach (streamedContent() as $chunk) {
  8. echo $chunk;
  9. ob_flush();
  10. flush();
  11. sleep(2); // Simulate delay between chunks...
  12. }
  13. }, 200, ['X-Accel-Buffering' => 'no']);
  14. });

内部的に、LaravelはPHPの出力バッファリング機能を利用しています。上記の例のように、ob_flushおよびflush関数を使用して、バッファされたコンテンツをクライアントにプッシュする必要があります。

ストリーミングJSON応答

JSONデータを段階的にストリーミングする必要がある場合は、streamJsonメソッドを利用できます。このメソッドは、JavaScriptによって簡単に解析できる形式でブラウザに段階的に送信する必要がある大規模データセットに特に便利です:

  1. use App\Models\User;
  2. Route::get('/users.json', function () {
  3. return response()->streamJson([
  4. 'users' => User::cursor(),
  5. ]);
  6. });

ストリーミングダウンロード

時には、特定の操作の文字列応答をダウンロード可能な応答に変換したい場合があります。この場合、streamDownloadメソッドを使用できます。このメソッドは、コールバック、ファイル名、およびオプションのヘッダーの配列を引数として受け入れます:

  1. use App\Services\GitHub;
  2. return response()->streamDownload(function () {
  3. echo GitHub::api('repo')
  4. ->contents()
  5. ->readme('laravel', 'laravel')['contents'];
  6. }, 'laravel-readme.md');

応答マクロ

さまざまなルートやコントローラーで再利用できるカスタム応答を定義したい場合は、macroメソッドをResponseファサードで使用できます。通常、このメソッドは、アプリケーションのサービスプロバイダーの1つのbootメソッドから呼び出す必要があります。たとえば、App\Providers\AppServiceProviderサービスプロバイダー:

  1. <?php
  2. namespace App\Providers;
  3. use Illuminate\Support\Facades\Response;
  4. use Illuminate\Support\ServiceProvider;
  5. class AppServiceProvider extends ServiceProvider
  6. {
  7. /**
  8. * Bootstrap any application services.
  9. */
  10. public function boot(): void
  11. {
  12. Response::macro('caps', function (string $value) {
  13. return Response::make(strtoupper($value));
  14. });
  15. }
  16. }
  1. ``````php
  2. return response()->caps('foo');
  3. `