#レスポンスの作成
#文字列と配列
すべてのルートやコントローラーは、ユーザーのブラウザに返すレスポンスを返す必要があります。Laravelはレスポンスを返すためのいくつかの方法を提供しています。最も基本的なレスポンスは、ルートやコントローラーから文字列を返すことです。フレームワークは文字列を自動的に完全なHTTPレスポンスに変換します:
Route::get('/', function () {
return 'Hello World';
});
ルートやコントローラーから文字列を返すことに加えて、配列を返すこともできます。フレームワークは配列を自動的にJSONレスポンスに変換します:
Route::get('/', function () {
return [1, 2, 3];
});
ルートやコントローラーからEloquentコレクションを返すこともできるのをご存知ですか?それらは自動的にJSONに変換されます。ぜひ試してみてください!
#レスポンスオブジェクト
通常、ルートアクションから単純な文字列や配列だけを返すことはありません。代わりに、完全なIlluminate\Http\Responseインスタンスやビューを返します。
完全なResponseインスタンスを返すことで、レスポンスのHTTPステータスコードやヘッダーをカスタマイズできます。ResponseインスタンスはSymfony\Component\HttpFoundation\Responseクラスを継承しており、HTTPレスポンスを構築するためのさまざまなメソッドを提供します:
Route::get('/home', function () {
return response('Hello World', 200)
->header('Content-Type', 'text/plain');
});
#Eloquentモデルとコレクション
ルートやコントローラーから直接Eloquent ORMのモデルやコレクションを返すこともできます。その場合、Laravelはモデルのhidden属性を尊重しつつ、自動的に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.headersミドルウェアが含まれており、ルートグループに対してCache-Controlヘッダーを簡単に設定できます。ディレクティブは対応するcache-controlディレクティブのスネークケース表記で指定し、セミコロンで区切ります。etagが指定されている場合、レスポンス内容のMD5ハッシュが自動的にETag識別子として設定されます:
Route::middleware('cache.headers:public;max_age=2628000;etag')->group(function () {
Route::get('/privacy', function () {
// ...
});
Route::get('/terms', function () {
// ...
});
});
#レスポンスへのクッキーの追加
Illuminate\Http\Responseインスタンスにクッキーを追加するには、cookieメソッドを使います。このメソッドにはクッキー名、値、有効期限(分)を渡します:
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');
#クッキーと暗号化
デフォルトで、Laravelが生成するすべてのクッキーは暗号化および署名されており、クライアントによる改ざんや読み取りを防ぎます。アプリケーションで生成されるクッキーの一部だけ暗号化を無効にしたい場合は、app/Http/MiddlewareディレクトリにあるApp\Http\Middleware\EncryptCookiesミドルウェアの$exceptプロパティを使います:
/**
* 暗号化しないクッキー名のリスト
*
* @var array
*/
protected $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 () {
// リクエストのバリデーション...
return back()->withInput();
});
#名前付きルートへのリダイレクト
redirectヘルパーをパラメータなしで呼ぶと、Illuminate\Routing\Redirectorのインスタンスが返され、Redirectorのメソッドを呼べます。例えば、名前付きルートへのRedirectResponseを生成するにはrouteメソッドを使います:
return redirect()->route('login');
ルートにパラメータがある場合は、routeメソッドの第2引数に渡せます:
// URIが /profile/{id} のルートの場合
return redirect()->route('profile', ['id' => 1]);
#Eloquentモデルによるパラメータの自動設定
EloquentモデルからIDパラメータを自動的に設定するルートにリダイレクトする場合は、モデル自体を渡せます。IDは自動的に抽出されます:
// URIが /profile/{id} のルートの場合
return redirect()->route('profile', [$user]);
ルートパラメータに入る値をカスタマイズしたい場合は、ルートパラメータ定義(/profile/{id:slug})でカラムを指定するか、EloquentモデルのgetRouteKeyメソッドをオーバーライドしてください:
/**
* モデルのルートキーの値を取得する
*/
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]
);
#外部ドメインへのリダイレクト
アプリケーション外のドメインにリダイレクトしたい場合は、awayメソッドを使います。これはURLのエンコードや検証なしでRedirectResponseを作成します:
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である必要があります。
#ストリームダウンロード
操作の文字列レスポンスをディスクに書き込まずにダウンロード可能なレスポンスに変換したい場合は、streamDownloadメソッドを使います。このメソッドはコールバック、ファイル名、オプションのヘッダー配列を引数に取ります:
use App\Services\GitHub;
return response()->streamDownload(function () {
echo GitHub::api('repo')
->contents()
->readme('laravel', 'laravel')['contents'];
}, 'laravel-readme.md');
#ファイルレスポンス
fileメソッドは、画像やPDFなどのファイルをユーザーのブラウザで直接表示し、ダウンロードを開始しません。このメソッドはファイルの絶対パスを第1引数に、ヘッダー配列を第2引数に取ります:
return response()->file($pathToFile);
return response()->file($pathToFile, $headers);
#レスポンスマクロ
ルートやコントローラーで再利用できるカスタムレスポンスを定義したい場合は、Responseファサードのmacroメソッドを使えます。通常はApp\Providers\AppServiceProviderなどのサービスプロバイダーのbootメソッド内で呼び出します:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* アプリケーションサービスのブートストラップ
*/
public function boot(): void
{
Response::macro('caps', function (string $value) {
return Response::make(strtoupper($value));
});
}
}
macro関数は第1引数に名前、第2引数にクロージャを受け取ります。マクロ名をResponseFactoryの実装やresponseヘルパーから呼ぶと、クロージャが実行されます:
return response()->caps('foo');