コンテンツへスキップ

HTTPレスポンス

レスポンスの作成

文字列と配列

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

Route::get('/', function () {
return 'Hello World';
});

ルートとコントローラから文字列を返すだけでなく、配列を返すこともできます。フレームワークは、配列をJSONレスポンスに自動的に変換します。

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

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);
exclamation

ファイルダウンロードを管理する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']);
});
lightbulb

内部的には、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');