#はじめに
LaravelのIlluminate\Http\Requestクラスは、現在処理中のHTTPリクエストにオブジェクト指向でアクセスし、リクエストと共に送信された入力、クッキー、ファイルを取得できます。
#リクエストとのやり取り
#リクエストへのアクセス
現在のHTTPリクエストのインスタンスを依存性注入で取得するには、ルートクロージャやコントローラーメソッドでIlluminate\Http\Requestクラスをタイプヒントしてください。Laravelのサービスコンテナが自動的にリクエストインスタンスを注入します:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* 新しいユーザーを保存します。
*/
public function store(Request $request): RedirectResponse
{
$name = $request->input('name');
// ユーザーを保存する処理...
return redirect('/users');
}
}
前述の通り、ルートクロージャでもIlluminate\Http\Requestクラスをタイプヒントできます。サービスコンテナが実行時に自動的にリクエストを注入します:
use Illuminate\Http\Request;
Route::get('/', function (Request $request) {
// ...
});
#依存性注入とルートパラメータ
コントローラーメソッドでルートパラメータも受け取る場合は、ルートパラメータを他の依存関係の後に記述してください。例えば、ルートが以下のように定義されている場合:
use App\Http\Controllers\UserController;
Route::put('/user/{id}', [UserController::class, 'update']);
Illuminate\Http\Requestをタイプヒントしつつ、idルートパラメータにアクセスするには、コントローラーメソッドを以下のように定義します:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* 指定したユーザーを更新します。
*/
public function update(Request $request, string $id): RedirectResponse
{
// ユーザーを更新する処理...
return redirect('/users');
}
}
#リクエストのパス、ホスト、メソッド
Illuminate\Http\Requestインスタンスは、受信したHTTPリクエストを調べるための多様なメソッドを提供し、Symfony\Component\HttpFoundation\Requestクラスを拡張しています。以下に重要なメソッドをいくつか紹介します。
#リクエストパスの取得
pathメソッドはリクエストのパス情報を返します。例えば、リクエストがhttp://example.com/foo/barに対して送信された場合、pathメソッドはfoo/barを返します:
$uri = $request->path();
#リクエストパス/ルートの検査
isメソッドを使うと、リクエストパスが指定したパターンにマッチするか確認できます。ワイルドカードとして*を使えます:
if ($request->is('admin/*')) {
// ...
}
routeIsメソッドを使うと、リクエストが名前付きルートにマッチしているか判定できます:
if ($request->routeIs('admin.*')) {
// ...
}
#リクエストURLの取得
リクエストの完全なURLを取得するには、urlまたはfullUrlメソッドを使います。urlはクエリ文字列なしのURLを返し、fullUrlはクエリ文字列を含みます:
$url = $request->url();
$urlWithQueryString = $request->fullUrl();
現在のURLにクエリ文字列を追加したい場合は、fullUrlWithQueryメソッドを呼び出します。このメソッドは指定したクエリ文字列の配列を現在のクエリ文字列とマージします:
$request->fullUrlWithQuery(['type' => 'phone']);
特定のクエリ文字列パラメータを除いた現在のURLを取得したい場合は、fullUrlWithoutQueryメソッドを使います:
$request->fullUrlWithoutQuery(['type']);
#リクエストホストの取得
リクエストの「ホスト」は、host、httpHost、schemeAndHttpHostメソッドで取得できます:
$request->host();
$request->httpHost();
$request->schemeAndHttpHost();
#リクエストメソッドの取得
methodメソッドはリクエストのHTTP動詞を返します。isMethodメソッドを使うと、HTTP動詞が指定した文字列と一致するか確認できます:
$method = $request->method();
if ($request->isMethod('post')) {
// ...
}
#リクエストヘッダー
Illuminate\Http\Request インスタンスから header メソッドを使ってリクエストヘッダーを取得できます。ヘッダーがリクエストに存在しない場合、null が返されます。ただし、header メソッドはオプションの第2引数を受け取り、ヘッダーが存在しない場合にその値が返されます:
$value = $request->header('X-Header-Name');
$value = $request->header('X-Header-Name', 'default');
hasHeaderメソッドを使うと、リクエストに特定のヘッダーが含まれているか判定できます:
if ($request->hasHeader('X-Header-Name')) {
// ...
}
利便性のため、bearerTokenメソッドでAuthorizationヘッダーからベアラートークンを取得できます。ヘッダーがなければ空文字列を返します:
$token = $request->bearerToken();
#リクエストのIPアドレス
ipメソッドで、リクエストを送信したクライアントのIPアドレスを取得できます:
$ipAddress = $request->ip();
プロキシ経由で転送されたすべてのクライアントIPアドレスを含む配列を取得したい場合は、ipsメソッドを使います。配列の最後が「元の」クライアントIPアドレスです:
$ipAddresses = $request->ips();
一般的に、IPアドレスは信頼できないユーザー制御の入力として扱い、情報取得のみに利用してください。
#コンテンツネゴシエーション
Laravelは、Acceptヘッダーを通じてリクエストが要求するコンテンツタイプを調べるための複数のメソッドを提供します。まず、getAcceptableContentTypesメソッドは、リクエストが受け入れるすべてのコンテンツタイプを配列で返します:
$contentTypes = $request->getAcceptableContentTypes();
acceptsメソッドはコンテンツタイプの配列を受け取り、リクエストがいずれかのタイプを受け入れる場合にtrueを返します。そうでなければfalseを返します:
if ($request->accepts(['text/html', 'application/json'])) {
// ...
}
prefersメソッドを使うと、指定したコンテンツタイプの中でリクエストが最も好むタイプを判定できます。どれも受け入れられない場合はnullを返します:
$preferred = $request->prefers(['text/html', 'application/json']);
多くのアプリケーションがHTMLかJSONのみを返すため、expectsJsonメソッドでリクエストがJSONレスポンスを期待しているか素早く判定できます:
if ($request->expectsJson()) {
// ...
}
#PSR-7リクエスト
PSR-7標準は、リクエストやレスポンスを含むHTTPメッセージのインターフェイスを定めています。Laravelリクエストの代わりにPSR-7リクエストのインスタンスを取得したい場合は、いくつかのライブラリをインストールする必要があります。LaravelはSymfony HTTP Message Bridgeコンポーネントを使い、通常のLaravelリクエストとレスポンスをPSR-7互換の実装に変換します:
composer require symfony/psr-http-message-bridge
composer require nyholm/psr7
これらのライブラリをインストールしたら、ルートクロージャやコントローラーメソッドでリクエストインターフェイスをタイプヒントしてPSR-7リクエストを取得できます:
use Psr\Http\Message\ServerRequestInterface;
Route::get('/', function (ServerRequestInterface $request) {
// ...
});
ルートやコントローラーからPSR-7レスポンスインスタンスを返すと、自動的にLaravelレスポンスインスタンスに変換され、フレームワークで表示されます。
#入力
#入力の取得
#すべての入力データの取得
allメソッドを使うと、受信したリクエストのすべての入力データをarrayとして取得できます。このメソッドはHTMLフォームからのリクエストでもXHRリクエストでも使えます:
$input = $request->all();
collectメソッドを使うと、受信したリクエストのすべての入力データをコレクションとして取得できます:
$input = $request->collect();
collectメソッドは、入力の一部をコレクションとして取得することも可能です:
$request->collect('users')->each(function (string $user) {
// ...
});
#入力値の取得
いくつかの簡単なメソッドを使うと、HTTP動詞に関係なくIlluminate\Http\Requestインスタンスからユーザー入力を取得できます。inputメソッドはHTTP動詞に関係なく入力を取得します:
$name = $request->input('name');
inputメソッドの第2引数にデフォルト値を渡すと、指定した入力値が存在しない場合にその値が返されます:
$name = $request->input('name', 'Sally');
配列入力を含むフォームを扱う場合は、「ドット」記法で配列にアクセスします:
$name = $request->input('products.0.name');
$names = $request->input('products.*.name');
引数なしでinputメソッドを呼ぶと、すべての入力値を連想配列として取得できます:
$input = $request->input();
#クエリ文字列からの入力取得
inputメソッドはリクエスト全体のペイロード(クエリ文字列も含む)から値を取得しますが、queryメソッドはクエリ文字列からのみ値を取得します:
$name = $request->query('name');
指定したクエリ文字列の値が存在しない場合は、第2引数の値が返されます:
$name = $request->query('name', 'Helen');
引数なしでqueryメソッドを呼ぶと、すべてのクエリ文字列の値を連想配列として取得できます:
$query = $request->query();
#JSON入力値の取得
JSONリクエストを送信する場合、リクエストのContent-Typeヘッダーが正しくapplication/jsonに設定されていれば、inputメソッドでJSONデータにアクセスできます。JSON配列やオブジェクト内のネストした値も「ドット」記法で取得可能です:
$name = $request->input('user.name');
#Stringable入力値の取得
リクエストの入力データをプリミティブなstringとしてではなく、Illuminate\Support\Stringableのインスタンスとして取得したい場合は、stringメソッドを使います:
$name = $request->string('name')->trim();
#ブール値入力の取得
チェックボックスなどのHTML要素を扱う際、実際には文字列である「truthy」な値(例:"true"や"on")を受け取ることがあります。booleanメソッドを使うと、これらの値をブール値として取得できます。booleanメソッドは1、"1"、true、"true"、"on"、"yes"をtrueとし、それ以外はfalseを返します:
$archived = $request->boolean('archived');
#日付入力値の取得
利便性のために、日付や時刻を含む入力値は date メソッドを使って Carbon インスタンスとして取得できます。指定した名前の入力値がリクエストに存在しない場合は、null が返されます。
$birthday = $request->date('birthday');
date メソッドの第2引数と第3引数は、それぞれ日付のフォーマットとタイムゾーンを指定するために使えます。
$elapsed = $request->date('elapsed', '!H:i', 'Europe/Madrid');
入力値が存在するがフォーマットが無効な場合は InvalidArgumentException がスローされます。そのため、date メソッドを呼び出す前に入力のバリデーションを行うことを推奨します。
#Enum 入力値の取得
PHPのenumに対応する入力値もリクエストから取得できます。指定した名前の入力値が存在しないか、enum に対応する値が入力値と一致しない場合は null が返されます。enum メソッドは入力値の名前と enum クラスをそれぞれ第1引数と第2引数に受け取ります。
use App\Enums\Status;
$status = $request->enum('status', Status::class);
#動的プロパティによる入力値の取得
Illuminate\Http\Request インスタンスの動的プロパティを使ってユーザー入力にアクセスすることもできます。例えば、アプリケーションのフォームに name フィールドがある場合、次のように値を取得できます。
$name = $request->name;
動的プロパティを使う場合、Laravel はまずリクエストペイロード内のパラメータ値を探します。存在しない場合は、マッチしたルートのパラメータからフィールドを検索します。
#入力データの一部を取得する
入力データの一部だけを取得したい場合は、only と except メソッドを使えます。どちらのメソッドも単一の array または可変長引数のリストを受け取ります。
$input = $request->only(['username', 'password']);
$input = $request->only('username', 'password');
$input = $request->except(['credit_card']);
$input = $request->except('credit_card');
only メソッドは要求したすべてのキーと値のペアを返しますが、リクエストに存在しないキーと値のペアは返しません。
#入力の存在確認
リクエストに値が存在するか確認するには、has メソッドを使用できます。has メソッドは、値がリクエストに存在する場合に true を返します:
if ($request->has('name')) {
// ...
}
配列を渡した場合、has メソッドは指定したすべての値が存在するかどうかを判定します。
if ($request->has(['name', 'email'])) {
// ...
}
hasAny メソッドは、指定した値のいずれかが存在すれば true を返します。
if ($request->hasAny(['name', 'email'])) {
// ...
}
whenHas メソッドは、指定した値が存在する場合にクロージャを実行します。
$request->whenHas('name', function (string $input) {
// ...
});
whenHas メソッドには第2のクロージャを渡せます。これは指定した値が存在しない場合に実行されます。
$request->whenHas('name', function (string $input) {
// "name" の値が存在する場合...
}, function () {
// "name" の値が存在しない場合...
});
値が存在し、かつ空文字列でないかを判定したい場合は、filled メソッドを使います。
if ($request->filled('name')) {
// ...
}
anyFilled メソッドは、指定した値のいずれかが空文字列でない場合に true を返します。
if ($request->anyFilled(['name', 'email'])) {
// ...
}
whenFilled メソッドは、値が存在し空文字列でない場合にクロージャを実行します。
$request->whenFilled('name', function (string $input) {
// ...
});
whenFilled メソッドには第2のクロージャを渡せます。これは指定した値が「filled」でない場合に実行されます。
$request->whenFilled('name', function (string $input) {
// "name" の値が filled である場合...
}, function () {
// "name" の値が filled でない場合...
});
指定したキーがリクエストに存在しないかどうかを判定するには、missing と whenMissing メソッドを使います。
if ($request->missing('name')) {
// ...
}
$request->whenMissing('name', function (array $input) {
// "name" の値が存在しない場合...
}, function () {
// "name" の値が存在する場合...
});
#追加入力のマージ
既存の入力データに手動で追加の入力をマージしたい場合は、merge メソッドを使います。指定したキーが既に存在する場合は、merge に渡したデータで上書きされます。
$request->merge(['votes' => 0]);
mergeIfMissing メソッドは、指定したキーがまだ存在しない場合にのみ入力をマージします。
$request->mergeIfMissing(['votes' => 0]);
#古い入力
Laravel は、次のリクエスト時に前回の入力を保持できます。この機能は、バリデーションエラー検出後にフォームを再入力する際に特に便利です。ただし、Laravel の組み込みのバリデーション機能を使っている場合は、これらのセッションへの入力フラッシュメソッドを手動で使う必要はほとんどありません。Laravel のバリデーション機能が自動的に呼び出します。
#セッションへの入力フラッシュ
Illuminate\Http\Request クラスの flash メソッドは、現在の入力をセッションにフラッシュし、次のリクエスト時に利用できるようにします。
$request->flash();
flashOnly と flashExcept メソッドを使うと、リクエストデータの一部だけをセッションにフラッシュできます。これらはパスワードなどの機密情報をセッションに含めたくない場合に便利です。
$request->flashOnly(['username', 'email']);
$request->flashExcept('password');
#入力をフラッシュしてリダイレクト
入力をセッションにフラッシュしてから前のページにリダイレクトしたい場合は、withInput メソッドを使って簡単にチェーンできます。
return redirect('form')->withInput();
return redirect()->route('user.create')->withInput();
return redirect('form')->withInput(
$request->except('password')
);
#古い入力の取得
前回のリクエストからフラッシュされた入力を取得するには、Illuminate\Http\Request のインスタンスで old メソッドを呼び出します。old メソッドはセッションから以前にフラッシュされた入力データを取得します。
$username = $request->old('username');
Laravel はグローバルな old ヘルパーも提供しています。Blade テンプレート内で古い入力を表示する場合は、old ヘルパーを使うほうが便利です。指定したフィールドに古い入力がなければ null が返されます。
<input type="text" name="username" value="{{ old('username') }}">
#クッキー
#リクエストからのクッキー取得
Laravel フレームワークで作成されたすべてのクッキーは暗号化され、認証コードで署名されています。つまり、クライアントによって改ざんされた場合は無効とみなされます。リクエストからクッキーの値を取得するには、Illuminate\Http\Request インスタンスの cookie メソッドを使います。
$value = $request->cookie('name');
#入力のトリミングと正規化
デフォルトで、Laravel は App\Http\Middleware\TrimStrings と Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull ミドルウェアをアプリケーションのグローバルミドルウェアスタックに含めています。これらは App\Http\Kernel クラスでグローバルミドルウェアスタックに登録されています。これらのミドルウェアはリクエストのすべての文字列フィールドを自動的にトリムし、空文字列のフィールドを null に変換します。これにより、ルートやコントローラーでこれらの正規化を気にする必要がなくなります。
#入力正規化の無効化
すべてのリクエストに対してこの動作を無効にしたい場合は、App\Http\Kernel クラスの $middleware プロパティからこれら2つのミドルウェアを削除してください。
アプリケーションへの一部のリクエストについて文字列のトリミングと空文字の null 変換を無効にしたい場合は、両方のミドルウェアが提供するskipWhenメソッドを使用できます。このメソッドはクロージャを受け取り、入力の正規化をスキップするかどうかを示すためにtrueまたはfalseを返す必要があります。通常、skipWhenメソッドはアプリケーションのAppServiceProviderのbootメソッド内で呼び出します。
use App\Http\Middleware\TrimStrings;
use Illuminate\Http\Request;
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
TrimStrings::skipWhen(function (Request $request) {
return $request->is('admin/*');
});
ConvertEmptyStringsToNull::skipWhen(function (Request $request) {
// ...
});
}
#ファイル
#アップロードされたファイルの取得
Illuminate\Http\Request インスタンスの file メソッドまたは動的プロパティを使ってアップロードされたファイルを取得できます。file メソッドは Illuminate\Http\UploadedFile クラスのインスタンスを返します。このクラスは PHP の SplFileInfo クラスを拡張しており、ファイル操作のためのさまざまなメソッドを提供します。
$file = $request->file('photo');
$file = $request->photo;
hasFile メソッドを使うと、リクエストにファイルが存在するかどうかを判定できます。
if ($request->hasFile('photo')) {
// ...
}
#アップロード成功のバリデーション
ファイルが存在するかどうかに加えて、isValid メソッドでアップロードに問題がなかったかを確認できます。
if ($request->file('photo')->isValid()) {
// ...
}
#ファイルパスと拡張子
UploadedFile クラスには、ファイルの完全なパスや拡張子を取得するメソッドもあります。extension メソッドはファイルの内容に基づいて拡張子を推測します。この拡張子はクライアントが送信した拡張子と異なる場合があります。
$path = $request->photo->path();
$extension = $request->photo->extension();
#その他のファイルメソッド
UploadedFile インスタンスには他にもさまざまなメソッドがあります。詳細はクラスのAPIドキュメントを参照してください。
#アップロードファイルの保存
アップロードされたファイルを保存するには、通常は設定済みのファイルシステムのいずれかを使います。UploadedFile クラスの store メソッドは、アップロードファイルをローカルファイルシステムや Amazon S3 のようなクラウドストレージのディスクに移動します。
store メソッドは、ファイルを保存するパスをファイルシステムのルートディレクトリからの相対パスで受け取ります。このパスにはファイル名を含めず、ファイル名は自動的に一意のIDで生成されます。
store メソッドは第2引数に保存先のディスク名をオプションで受け取れます。メソッドはディスクのルートからのファイルパスを返します。
$path = $request->photo->store('images');
$path = $request->photo->store('images', 's3');
ファイル名を自動生成したくない場合は、パス、ファイル名、ディスク名を引数に取る storeAs メソッドを使えます。
$path = $request->photo->storeAs('images', 'filename.jpg');
$path = $request->photo->storeAs('images', 'filename.jpg', 's3');
Laravel のファイルストレージについて詳しくは、完全なファイルストレージのドキュメントを参照してください。
#信頼できるプロキシの設定
TLS / SSL証明書を終端するロードバランサーの背後でアプリケーションを実行している場合、url ヘルパーを使ってもHTTPSリンクが生成されないことがあります。これは通常、ロードバランサーからポート80で転送されたトラフィックを受けており、アプリケーションが安全なリンクを生成すべきだと認識していないためです。
これを解決するには、Laravelアプリケーションに含まれる App\Http\Middleware\TrustProxies ミドルウェアを使うと便利です。これにより、信頼すべきロードバランサーやプロキシを簡単にカスタマイズできます。信頼するプロキシは、このミドルウェアの $proxies プロパティに配列として指定します。さらに、信頼するプロキシの $headers も設定可能です。
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
/**
* このアプリケーションで信頼するプロキシ。
*
* @var string|array
*/
protected $proxies = [
'192.168.1.1',
'192.168.1.2',
];
/**
* プロキシを検出するために使用するヘッダー。
*
* @var int
*/
protected $headers = Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO;
}
AWS Elastic Load Balancingを使用している場合、$headers の値は Request::HEADER_X_FORWARDED_AWS_ELB に設定してください。$headers プロパティで使用可能な定数の詳細は、Symfonyのtrusting proxiesドキュメントをご覧ください。
#すべてのプロキシを信頼する
Amazon AWSやその他のクラウドロードバランサープロバイダーを使っている場合、実際のロードバランサーのIPアドレスがわからないことがあります。その場合、* を使ってすべてのプロキシを信頼できます。
/**
* このアプリケーションで信頼するプロキシ。
*
* @var string|array
*/
protected $proxies = '*';
#信頼するホストの設定
デフォルトでは、LaravelはHTTPリクエストの Host ヘッダーの内容に関係なく、受け取ったすべてのリクエストに応答します。また、Host ヘッダーの値はウェブリクエスト時に絶対URLを生成する際に使用されます。
通常は、NginxやApacheなどのウェブサーバーで、特定のホスト名に一致するリクエストのみをアプリケーションに送るよう設定します。しかし、ウェブサーバーを直接カスタマイズできず、Laravelに特定のホスト名だけに応答させたい場合は、App\Http\Middleware\TrustHosts ミドルウェアを有効にしてください。
TrustHosts ミドルウェアはすでにアプリケーションの $middleware スタックに含まれていますが、コメントアウトされているため有効化する必要があります。このミドルウェアの hosts メソッド内で、応答すべきホスト名を指定できます。指定外の Host ヘッダーを持つリクエストは拒否されます。
/**
* 信頼するホストのパターンを取得する。
*
* @return array<int, string>
*/
public function hosts(): array
{
return [
'laravel.test',
$this->allSubdomainsOfApplicationUrl(),
];
}
allSubdomainsOfApplicationUrl ヘルパーメソッドは、アプリケーションの app.url 設定値のすべてのサブドメインにマッチする正規表現を返します。このメソッドは、ワイルドカードサブドメインを使うアプリケーションで、すべてのサブドメインを許可する便利な方法です。