ルーティング
- 基本ルーティング
- ルートパラメータ
- 名前付きルート
- ルートグループ
- ルートモデル結合
- フォールバックルート
- レート制限
- フォームメソッド偽装
- 現在ルートへのアクセス
- Cross-Origin Resource Sharing (CORS)
- ルートキャッシュ
基本ルーティング
最も基本的なLaravelのルートはURIとクロージャを受け入れ、複雑なルーティング設定ファイルなしでルートと動作を定義する非常にシンプルで表現豊かなメソッドを提供します。
1use Illuminate\Support\Facades\Route;2 3Route::get('/greeting', function () {4 return 'Hello World';5});
デフォルトルートファイル
すべてのLaravelルートは、routesディレクトリにあるルートファイルで定義します。これらのファイルは、アプリケーションのbootstrap/app.phpファイルで指定した設定を使用してLaravelによって自動的にロードされます。routes/web.phpファイルは、Webインターフェイス用のルートを定義します。これらのルートにはweb ミドルウェアグループが割り当てられ、セッション状態やCSRF保護などの機能を提供します。
ほとんどのアプリケーションでは、routes/web.phpファイルでルートを定義することから始めます。routes/web.phpで定義されたルートへは、定義されたルートのURLをブラウザに入力することでアクセスできます。たとえば、ブラウザでhttp://example.com/userにアクセスすると、次のルートにアクセスできます。
1use App\Http\Controllers\UserController;2 3Route::get('/user', [UserController::class, 'index']);
APIルート
アプリケーションがステートレスAPIも提供する場合は、install:api Artisanコマンドを使用してAPIルーティングを有効にできます。
1php artisan install:api
install:apiコマンドは、Laravel Sanctumをインストールします。Sanctumは、サードパーティのAPIコンシューマ、SPA、またはモバイルアプリケーションを認証するために使用できる、堅牢でシンプルなAPIトークン認証ガードを提供します。さらに、install:apiコマンドはroutes/api.phpファイルを作成します。
1Route::get('/user', function (Request $request) {2 return $request->user();3})->middleware('auth:sanctum');
routes/api.phpのルートはステートレスであり、api ミドルウェアグループに割り当てられます。さらに、/api URIプレフィックスがこれらのルートに自動的に適用されるため、ファイル内のすべてのルートに手動で適用する必要はありません。プレフィックスは、アプリケーションのbootstrap/app.phpファイルを変更することで変更できます。
1->withRouting(2 api: __DIR__.'/../routes/api.php',3 apiPrefix: 'api/admin',4 // ...5)
利用可能なルータメソッド
ルータを使用すると、任意のHTTP動詞に応答するルートを登録できます。
1Route::get($uri, $callback);2Route::post($uri, $callback);3Route::put($uri, $callback);4Route::patch($uri, $callback);5Route::delete($uri, $callback);6Route::options($uri, $callback);
複数のHTTP動詞に応答するルートを登録する必要がある場合もあります。matchメソッドを使用して実行できます。または、anyメソッドを使用して、すべてのHTTP動詞に応答するルートを登録することもできます。
1Route::match(['get', 'post'], '/', function () {2 // ...3});4 5Route::any('/', function () {6 // ...7});
同じURIを共有する複数のルートを定義する場合、get、post、put、patch、delete、optionsメソッドを使用するルートは、any、match、redirectメソッドを使用するルートより前に定義する必要があります。これにより、受信リクエストが正しいルートと一致することが保証されます。
依存注入
ルートで必要な依存関係を、ルートのコールバックシグネチャでタイプヒントできます。宣言された依存関係は、Laravelのサービスコンテナによって自動的に解決され、コールバックに注入されます。たとえば、Illuminate\Http\Requestクラスをタイプヒントして、現在のHTTPリクエストをルートコールバックに自動的に注入させることができます。
1use Illuminate\Http\Request;2 3Route::get('/users', function (Request $request) {4 // ...5});
CSRF保護
webルートファイルで定義されているPOST、PUT、PATCH、またはDELETEルートを指すHTMLフォームには、CSRFトークンフィールドを含める必要があることに注意してください。そうしないと、リクエストは拒否されます。CSRF保護の詳細は、CSRFドキュメントで確認してください。
1<form method="POST" action="/profile">2 @csrf3 ...4</form>
リダイレクトルート
別のURIにリダイレクトするルートを定義している場合は、Route::redirectメソッドを使用できます。このメソッドは便利なショートカットを提供するため、単純なリダイレクトを実行するために完全なルートやコントローラを定義する必要はありません。
1Route::redirect('/here', '/there');
デフォルトで、Route::redirectは302ステータスコードを返します。オプションの3番目のパラメータを使用して、ステータスコードをカスタマイズできます。
1Route::redirect('/here', '/there', 301);
または、Route::permanentRedirectメソッドを使用して、301ステータスコードを返すこともできます。
1Route::permanentRedirect('/here', '/there');
リダイレクトルートでルートパラメータを使用する場合、Laravelでは次のパラメータが予約されており、使用できません:destination、status。
ビュールート
ルートがビューを返すだけでよい場合は、Route::viewメソッドを使用できます。redirectメソッドと同様に、このメソッドは単純なショートカットを提供するため、完全なルートやコントローラを定義する必要はありません。viewメソッドは、最初の引数としてURIを、2番目の引数としてビュー名を受け入れます。さらに、オプションの3番目の引数として、ビューに渡すデータの配列を指定できます。
1Route::view('/welcome', 'welcome');2 3Route::view('/welcome', 'welcome', ['name' => 'Taylor']);
ビュールートでルートパラメータを使用する場合、Laravelでは次のパラメータが予約されており、使用できません:view、data、status、headers。
ルートの一覧表示
route:list Artisanコマンドは、アプリケーションで定義されているすべてのルートの概要を簡単に提供できます。
1php artisan route:list
デフォルトでは、各ルートに割り当てられているルートミドルウェアはroute:listの出力に表示されません。しかし、コマンドに-vオプションを追加することで、Laravelにルートミドルウェアとミドルウェアグループ名を表示するように指示できます。
1php artisan route:list -v2 3# Expand middleware groups...4php artisan route:list -vv
特定のURIで始まるルートのみを表示するようにLaravelに指示することもできます。
1php artisan route:list --path=api
さらに、route:listコマンドの実行時に--except-vendorオプションを指定することで、サードパーティのパッケージによって定義されたルートを非表示にするようにLaravelに指示できます。
1php artisan route:list --except-vendor
同様に、route:listコマンドの実行時に--only-vendorオプションを指定することで、サードパーティのパッケージによって定義されたルートのみを表示するようにLaravelに指示することもできます。
1php artisan route:list --only-vendor
ルーティングのカスタマイズ
デフォルトでは、アプリケーションのルートはbootstrap/app.phpファイルによって設定およびロードされます。
1<?php 2 3use Illuminate\Foundation\Application; 4 5return Application::configure(basePath: dirname(__DIR__)) 6 ->withRouting( 7 web: __DIR__.'/../routes/web.php', 8 commands: __DIR__.'/../routes/console.php', 9 health: '/up',10 )->create();
ただし、アプリケーションのルートのサブセットを格納するために、まったく新しいファイルを定義したい場合があります。これを実現するには、withRoutingメソッドにthenクロージャを指定します。このクロージャ内で、アプリケーションに必要な追加のルートを登録できます。
1use Illuminate\Support\Facades\Route; 2 3->withRouting( 4 web: __DIR__.'/../routes/web.php', 5 commands: __DIR__.'/../routes/console.php', 6 health: '/up', 7 then: function () { 8 Route::middleware('api') 9 ->prefix('webhooks')10 ->name('webhooks.')11 ->group(base_path('routes/webhooks.php'));12 },13)
または、withRoutingメソッドにusingクロージャを指定することで、ルート登録を完全に制御することもできます。この引数を渡すと、フレームワークによってHTTPルートは登録されなくなり、すべてのルートを手動で登録する責任を負います。
1use Illuminate\Support\Facades\Route; 2 3->withRouting( 4 commands: __DIR__.'/../routes/console.php', 5 using: function () { 6 Route::middleware('api') 7 ->prefix('api') 8 ->group(base_path('routes/api.php')); 9 10 Route::middleware('web')11 ->group(base_path('routes/web.php'));12 },13)
ルートパラメータ
必須パラメータ
ルート内でURIのセグメントをキャプチャする必要がある場合があります。たとえば、URLからユーザーのIDをキャプチャする必要があるかもしれません。これは、ルートパラメータを定義することで実現できます。
1Route::get('/user/{id}', function (string $id) {2 return 'User '.$id;3});
ルートで必要なだけ、ルートパラメータを定義できます。
1Route::get('/posts/{post}/comments/{comment}', function (string $postId, string $commentId) {2 // ...3});
ルートパラメータは常に{}で囲み、アルファベット文字で構成する必要があります。ルートパラメータ名にはアンダースコア(_)も使用できます。ルートパラメータは、その順序に基づいてルートコールバック/コントローラに注入されます。ルートコールバック/コントローラの引数名は関係ありません。
パラメータと依存注入
ルートにLaravelサービスコンテナが自動的にルートのコールバックに注入してほしい依存関係がある場合は、ルートパラメータを依存関係の後にリストする必要があります。
1use Illuminate\Http\Request;2 3Route::get('/user/{id}', function (Request $request, string $id) {4 return 'User '.$id;5});
任意パラメータ
URIに常に存在するとは限らないルートパラメータを指定する必要がある場合があります。パラメータ名の後に?を付けることで、これを行えます。ルートの対応する変数にデフォルト値を与えるようにしてください。
1Route::get('/user/{name?}', function (?string $name = null) {2 return $name;3});4 5Route::get('/user/{name?}', function (?string $name = 'John') {6 return $name;7});
正規表現制約
ルートインスタンスのwhereメソッドを使用して、ルートパラメータの形式を制約できます。whereメソッドは、パラメータの名前と、パラメータをどのように制約するかを定義する正規表現を受け入れます。
1Route::get('/user/{name}', function (string $name) { 2 // ... 3})->where('name', '[A-Za-z]+'); 4 5Route::get('/user/{id}', function (string $id) { 6 // ... 7})->where('id', '[0-9]+'); 8 9Route::get('/user/{id}/{name}', function (string $id, string $name) {10 // ...11})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
便宜上、一般的に使用される正規表現パターンには、ルートにパターン制約をすばやく追加できるヘルパメソッドがあります。
1Route::get('/user/{id}/{name}', function (string $id, string $name) { 2 // ... 3})->whereNumber('id')->whereAlpha('name'); 4 5Route::get('/user/{name}', function (string $name) { 6 // ... 7})->whereAlphaNumeric('name'); 8 9Route::get('/user/{id}', function (string $id) {10 // ...11})->whereUuid('id');12 13Route::get('/user/{id}', function (string $id) {14 // ...15})->whereUlid('id');16 17Route::get('/category/{category}', function (string $category) {18 // ...19})->whereIn('category', ['movie', 'song', 'painting']);20 21Route::get('/category/{category}', function (string $category) {22 // ...23})->whereIn('category', CategoryEnum::cases());
受信リクエストがルートパターンの制約に一致しない場合、404 HTTPレスポンスが返されます。
グローバル制約
ルートパラメータを常に特定の正規表現で制約したい場合は、patternメソッドを使用できます。これらのパターンは、アプリケーションのApp\Providers\AppServiceProviderクラスのbootメソッドで定義する必要があります。
1use Illuminate\Support\Facades\Route;2 3/**4 * Bootstrap any application services.5 */6public function boot(): void7{8 Route::pattern('id', '[0-9]+');9}
パターンが定義されると、そのパラメータ名を使用するすべてのルートに自動的に適用されます。
1Route::get('/user/{id}', function (string $id) {2 // Only executed if {id} is numeric...3});
エンコードされたフォワードスラッシュ
Laravelのルーティングコンポーネントは、/を除くすべての文字がルートパラメータ値内に存在することを許可します。where条件の正規表現を使用して、プレースホルダーの一部として/を明示的に許可する必要があります。
1Route::get('/search/{search}', function (string $search) {2 return $search;3})->where('search', '.*');
エンコードされたフォワードスラッシュは、最後のルートセグメント内でのみサポートされます。
名前付きルート
名前付きルートを使用すると、特定のルートのURLやリダイレクトを便利に生成できます。ルート定義にnameメソッドをチェーンすることで、ルートに名前を指定できます。
1Route::get('/user/profile', function () {2 // ...3})->name('profile');
コントローラアクションのルート名を指定することもできます。
1Route::get(2 '/user/profile',3 [UserProfileController::class, 'show']4)->name('profile');
ルート名は常に一意である必要があります。
名前付きルートへのURLの生成
特定のルートに名前を割り当てたら、Laravelのrouteおよびredirectヘルパ関数を介してURLまたはリダイレクトを生成するときに、そのルートの名前を使用できます。
1// Generating URLs...2$url = route('profile');3 4// Generating Redirects...5return redirect()->route('profile');6 7return to_route('profile');
名前付きルートがパラメータを定義している場合は、route関数の2番目の引数としてパラメータを渡すことができます。指定されたパラメータは、生成されたURLの正しい位置に自動的に挿入されます。
1Route::get('/user/{id}/profile', function (string $id) {2 // ...3})->name('profile');4 5$url = route('profile', ['id' => 1]);
配列に追加のパラメータを渡すと、それらのキー/値のペアは生成されたURLのクエリ文字列に自動的に追加されます。
1Route::get('/user/{id}/profile', function (string $id) {2 // ...3})->name('profile');4 5$url = route('profile', ['id' => 1, 'photos' => 'yes']);6 7// /user/1/profile?photos=yes
現在のロケールなど、URLパラメータのデフォルト値をリクエスト全体で指定したい場合があります。これを実現するには、URL::defaultsメソッドを使用します。
現在のルートの検査
現在のリクエストが特定名前付きのルートにルーティングされたかどうかを判断したい場合は、Routeインスタンスでnamedメソッドを使用できます。たとえば、ルートミドルウェアから現在のルート名を確認できます。
1use Closure; 2use Illuminate\Http\Request; 3use Symfony\Component\HttpFoundation\Response; 4 5/** 6 * Handle an incoming request. 7 * 8 * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next 9 */10public function handle(Request $request, Closure $next): Response11{12 if ($request->route()->named('profile')) {13 // ...14 }15 16 return $next($request);17}
ルートグループ
ルートグループを使用すると、ミドルウェアなどのルート属性を、個々のルートでそれらの属性を定義する必要なく、多数のルートで共有できます。
ネストされたグループは、親グループと属性をインテリジェントに「マージ」しようとします。ミドルウェアとwhere条件はマージされ、名前とプレフィックスは追加されます。名前空間の区切り文字とURIプレフィックスのスラッシュは、適切な場所で自動的に追加されます。
ミドルウェア
グループ内のすべてのルートにミドルウェアを割り当てるには、グループを定義する前にmiddlewareメソッドを使用します。ミドルウェアは、配列にリストされている順序で実行されます。
1Route::middleware(['first', 'second'])->group(function () {2 Route::get('/', function () {3 // Uses first & second middleware...4 });5 6 Route::get('/user/profile', function () {7 // Uses first & second middleware...8 });9});
コントローラ
ルートのグループがすべて同じコントローラを利用する場合、controllerメソッドを使用して、グループ内のすべてのルートの共通コントローラを定義できます。その後、ルートを定義するときは、それらが呼び出すコントローラメソッドを指定するだけで済みます。
1use App\Http\Controllers\OrderController;2 3Route::controller(OrderController::class)->group(function () {4 Route::get('/orders/{id}', 'show');5 Route::post('/orders', 'store');6});
サブドメインルーティング
ルートグループは、サブドメインルーティングを処理するためにも使用できます。サブドメインには、ルートURIと同様にルートパラメータを割り当てることができ、ルートまたはコントローラで使用するためにサブドメインの一部をキャプチャできます。サブドメインは、グループを定義する前にdomainメソッドを呼び出すことによって指定できます。
1Route::domain('{account}.example.com')->group(function () {2 Route::get('/user/{id}', function (string $account, string $id) {3 // ...4 });5});
サブドメインルートに到達できるようにするには、ルートドメインルートを登録する前にサブドメインルートを登録する必要があります。これにより、ルートドメインルートが同じURIパスを持つサブドメインルートを上書きするのを防ぎます。
ルートプレフィックス
prefixメソッドを使用して、グループ内の各ルートに特定のURIをプレフィックスとして付けることができます。たとえば、グループ内のすべてのルートURIにadminをプレフィックスとして付けたい場合があります。
1Route::prefix('admin')->group(function () {2 Route::get('/users', function () {3 // Matches The "/admin/users" URL4 });5});
ルート名プレフィックス
nameメソッドを使用して、グループ内の各ルート名に特定の文字列をプレフィックスとして付けることができます。たとえば、グループ内のすべてのルートの名前にadminをプレフィックスとして付けたい場合があります。指定された文字列は、指定されたとおりにルート名の前に付けられるため、プレフィックスの末尾に.文字を必ず指定します。
1Route::name('admin.')->group(function () {2 Route::get('/users', function () {3 // Route assigned name "admin.users"...4 })->name('users');5});
ルートモデル結合
モデルIDをルートまたはコントローラアクションに注入する場合、多くの場合、データベースをクエリしてそのIDに対応するモデルを取得します。Laravelのルートモデル結合は、モデルインスタンスをルートに直接自動的に注入する便利な方法を提供します。たとえば、ユーザーのIDを注入する代わりに、指定されたIDに一致するUserモデルインスタンス全体を注入できます。
暗黙の結合
Laravelは、タイプヒントされた変数名がルートセグメント名と一致するルートまたはコントローラアクションで定義されたEloquentモデルを自動的に解決します。たとえば、
1use App\Models\User;2 3Route::get('/users/{user}', function (User $user) {4 return $user->email;5});
$user変数はApp\Models\User Eloquentモデルとしてタイプヒントされており、変数名が{user} URIセグメントと一致するため、LaravelはリクエストURIの対応する値と一致するIDを持つモデルインスタンスを自動的に注入します。一致するモデルインスタンスがデータベースに見つからない場合、404 HTTPレスポンスが自動的に生成されます。
もちろん、コントローラメソッドを使用する場合でも、暗黙の結合は可能です。ここでも、{user} URIセグメントが、App\Models\Userタイプヒントを含むコントローラの$user変数と一致することに注意してください。
1use App\Http\Controllers\UserController; 2use App\Models\User; 3 4// Route definition... 5Route::get('/users/{user}', [UserController::class, 'show']); 6 7// Controller method definition... 8public function show(User $user) 9{10 return view('user.profile', ['user' => $user]);11}
ソフトデリートされたモデル
通常、暗黙のモデル結合ではソフトデリートされたモデルは取得されません。しかし、ルートの定義にwithTrashedメソッドをチェーンすることで、暗黙の結合でこれらのモデルを取得するように指示できます。
1use App\Models\User;2 3Route::get('/users/{user}', function (User $user) {4 return $user->email;5})->withTrashed();
キーのカスタマイズ
Eloquentモデルをid以外のカラムを使用して解決したい場合があります。その場合は、ルートパラメータ定義でカラムを指定できます。
1use App\Models\Post;2 3Route::get('/posts/{post:slug}', function (Post $post) {4 return $post;5});
特定のモデルクラスを取得する際に、モデル結合で常にid以外のデータベースカラムを使用したい場合は、EloquentモデルのgetRouteKeyNameメソッドをオーバーライドできます。
1/**2 * Get the route key for the model.3 */4public function getRouteKeyName(): string5{6 return 'slug';7}
カスタムキーとスコープ
単一のルート定義で複数のEloquentモデルを暗黙的に結合する場合、2番目のEloquentモデルが前のEloquentモデルの子である必要があるように、スコープを設定したい場合があります。たとえば、特定のユーザーのブログ投稿をスラッグで取得する次のルート定義を考えてみましょう。
1use App\Models\Post;2use App\Models\User;3 4Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {5 return $post;6});
ネストされたルートパラメータとしてカスタムキー付きの暗黙の結合を使用する場合、Laravelは親の関連名を推測する規約を使用して、親によってネストされたモデルを取得するクエリを自動的にスコープします。この場合、Userモデルには、Postモデルを取得するために使用できるposts(ルートパラメータ名の複数形)という名前の関連があると想定されます。
必要であれば、カスタムキーが提供されていない場合でも、「子」の結合をスコープするようにLaravelに指示できます。そのためには、ルートを定義するときにscopeBindingsメソッドを呼び出します。
1use App\Models\Post;2use App\Models\User;3 4Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {5 return $post;6})->scopeBindings();
または、ルート定義のグループ全体にスコープ付きの結合を使用するように指示することもできます。
1Route::scopeBindings()->group(function () {2 Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {3 return $post;4 });5});
同様に、withoutScopedBindingsメソッドを呼び出すことで、結合をスコープしないようにLaravelに明示的に指示することもできます。
1Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {2 return $post;3})->withoutScopedBindings();
見つからないモデルの動作のカスタマイズ
通常、暗黙的に結合されたモデルが見つからない場合、404 HTTPレスポンスが生成されます。ただし、ルートを定義するときにmissingメソッドを呼び出すことで、この動作をカスタマイズできます。missingメソッドは、暗黙的に結合されたモデルが見つからない場合に呼び出されるクロージャを受け入れます。
1use App\Http\Controllers\LocationsController;2use Illuminate\Http\Request;3use Illuminate\Support\Facades\Redirect;4 5Route::get('/locations/{location:slug}', [LocationsController::class, 'show'])6 ->name('locations.view')7 ->missing(function (Request $request) {8 return Redirect::route('locations.index');9 });
暗黙のEnum結合
PHP 8.1では、Enumのサポートが導入されました。この機能を補完するために、Laravelではルート定義でstring-backed Enumをタイプヒントすることができ、そのルートセグメントが有効なEnum値に対応する場合にのみLaravelはルートを呼び出します。そうでない場合、404 HTTPレスポンスが自動的に返されます。たとえば、次のEnumが与えられたとします。
1<?php2 3namespace App\Enums;4 5enum Category: string6{7 case Fruits = 'fruits';8 case People = 'people';9}
{category}ルートセグメントがfruitsまたはpeopleである場合にのみ呼び出されるルートを定義できます。それ以外の場合、Laravelは404 HTTPレスポンスを返します。
1use App\Enums\Category;2use Illuminate\Support\Facades\Route;3 4Route::get('/categories/{category}', function (Category $category) {5 return $category->value;6});
明示的な結合
モデル結合を使用するために、Laravelの暗黙的で規約ベースのモデル解決を使用する必要はありません。ルートパラメータがモデルにどのように対応するかを明示的に定義することもできます。明示的な結合を登録するには、ルータのmodelメソッドを使用して、特定のパラメータのクラスを指定します。明示的なモデル結合は、AppServiceProviderクラスのbootメソッドの先頭で定義する必要があります。
1use App\Models\User; 2use Illuminate\Support\Facades\Route; 3 4/** 5 * Bootstrap any application services. 6 */ 7public function boot(): void 8{ 9 Route::model('user', User::class);10}
次に、{user}パラメータを含むルートを定義します。
1use App\Models\User;2 3Route::get('/users/{user}', function (User $user) {4 // ...5});
すべての{user}パラメータをApp\Models\Userモデルに結合したので、そのクラスのインスタンスがルートに注入されます。したがって、たとえば、users/1へのリクエストは、IDが1であるデータベースからUserインスタンスを注入します。
一致するモデルインスタンスがデータベースに見つからない場合、404 HTTPレスポンスが自動的に生成されます。
解決ロジックのカスタマイズ
独自のモデル結合解決ロジックを定義したい場合は、Route::bindメソッドを使用できます。bindメソッドに渡すクロージャは、URIセグメントの値を受け取り、ルートに注入されるべきクラスのインスタンスを返す必要があります。繰り返しになりますが、このカスタマイズはアプリケーションのAppServiceProviderのbootメソッドで行う必要があります。
1use App\Models\User; 2use Illuminate\Support\Facades\Route; 3 4/** 5 * Bootstrap any application services. 6 */ 7public function boot(): void 8{ 9 Route::bind('user', function (string $value) {10 return User::where('name', $value)->firstOrFail();11 });12}
あるいは、EloquentモデルのresolveRouteBindingメソッドをオーバーライドすることもできます。このメソッドはURIセグメントの値を受け取り、ルートに注入されるべきクラスのインスタンスを返す必要があります。
1/** 2 * Retrieve the model for a bound value. 3 * 4 * @param mixed $value 5 * @param string|null $field 6 * @return \Illuminate\Database\Eloquent\Model|null 7 */ 8public function resolveRouteBinding($value, $field = null) 9{10 return $this->where('name', $value)->firstOrFail();11}
ルートが暗黙の結合スコープを利用している場合、親モデルの子の結合を解決するためにresolveChildRouteBindingメソッドが使用されます。
1/** 2 * Retrieve the child model for a bound value. 3 * 4 * @param string $childType 5 * @param mixed $value 6 * @param string|null $field 7 * @return \Illuminate\Database\Eloquent\Model|null 8 */ 9public function resolveChildRouteBinding($childType, $value, $field)10{11 return parent::resolveChildRouteBinding($childType, $value, $field);12}
フォールバックルート
Route::fallbackメソッドを使用すると、受信リクエストに一致する他のルートがない場合に実行されるルートを定義できます。通常、未処理のリクエストは、アプリケーションの例外ハンドラを介して自動的に「404」ページをレンダリングします。ただし、通常はroutes/web.phpファイル内でfallbackルートを定義するため、webミドルウェアグループ内のすべてのミドルウェアがそのルートに適用されます。必要に応じて、このルートに追加のミドルウェアを自由に追加できます。
1Route::fallback(function () {2 // ...3});
レート制限
レートリミッタの定義
Laravelには、特定のルートまたはルートグループのトラフィック量を制限するために利用できる、強力でカスタマイズ可能なレート制限サービスが含まれています。開始するには、アプリケーションのニーズを満たすレートリミッタ設定を定義する必要があります。
レートリミッタは、アプリケーションのApp\Providers\AppServiceProviderクラスのbootメソッド内で定義できます。
1use Illuminate\Cache\RateLimiting\Limit; 2use Illuminate\Http\Request; 3use Illuminate\Support\Facades\RateLimiter; 4 5/** 6 * Bootstrap any application services. 7 */ 8protected function boot(): void 9{10 RateLimiter::for('api', function (Request $request) {11 return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());12 });13}
レートリミッタは、RateLimiterファサードのforメソッドを使用して定義します。forメソッドは、レートリミッタ名と、そのレートリミッタに割り当てられているルートに適用されるべき制限設定を返すクロージャを受け入れます。制限設定は、Illuminate\Cache\RateLimiting\Limitクラスのインスタンスです。このクラスには、制限を迅速に定義できるようにするための便利な「ビルダー」メソッドが含まれています。レートリミッタ名は、任意の文字列にすることができます。
1use Illuminate\Cache\RateLimiting\Limit; 2use Illuminate\Http\Request; 3use Illuminate\Support\Facades\RateLimiter; 4 5/** 6 * Bootstrap any application services. 7 */ 8protected function boot(): void 9{10 RateLimiter::for('global', function (Request $request) {11 return Limit::perMinute(1000);12 });13}
受信リクエストが指定されたレート制限を超えた場合、429 HTTPステータスコードを持つレスポンスがLaravelによって自動的に返されます。レート制限によって返されるべき独自のレスポンスを定義したい場合は、responseメソッドを使用できます。
1RateLimiter::for('global', function (Request $request) {2 return Limit::perMinute(1000)->response(function (Request $request, array $headers) {3 return response('Custom response...', 429, $headers);4 });5});
レートリミッタのコールバックは受信HTTPリクエストインスタンスを受け取るため、受信リクエストまたは認証済みユーザーに基づいて適切なレート制限を動的に構築できます。
1RateLimiter::for('uploads', function (Request $request) {2 return $request->user()->vipCustomer()3 ? Limit::none()4 : Limit::perMinute(100);5});
レート制限のセグメント化
レート制限を任意の価でセグメント化したい場合があります。たとえば、ユーザーがIPアドレスごとに1分あたり100回、特定のルートにアクセスできるようにしたい場合があります。これを実現するには、レート制限を構築するときにbyメソッドを使用します。
1RateLimiter::for('uploads', function (Request $request) {2 return $request->user()->vipCustomer()3 ? Limit::none()4 : Limit::perMinute(100)->by($request->ip());5});
この機能を別の例で説明するために、認証済みユーザーIDごとに1分あたり100回、またはゲストの場合はIPアドレスごとに1分あたり10回にルートへのアクセスを制限できます。
1RateLimiter::for('uploads', function (Request $request) {2 return $request->user()3 ? Limit::perMinute(100)->by($request->user()->id)4 : Limit::perMinute(10)->by($request->ip());5});
複数のレート制限
必要に応じて、特定のレートリミッタ設定に対してレート制限の配列を返すことができます。各レート制限は、配列内に配置された順序に基づいてルートに対して評価されます。
1RateLimiter::for('login', function (Request $request) {2 return [3 Limit::perMinute(500),4 Limit::perMinute(3)->by($request->input('email')),5 ];6});
同一のby値でセグメント化された複数のレート制限を割り当てる場合は、各by値が一意であることを確認する必要があります。これを実現する最も簡単な方法は、byメソッドに与える値にプレフィックスを付けることです。
1RateLimiter::for('uploads', function (Request $request) {2 return [3 Limit::perMinute(10)->by('minute:'.$request->user()->id),4 Limit::perDay(1000)->by('day:'.$request->user()->id),5 ];6});
ルートへのレートリミッタの適用
レートリミッタは、throttle ミドルウェアを使用してルートまたはルートグループにアタッチできます。throttleミドルウェアは、ルートに割り当てたいレートリミッタの名前を受け入れます。
1Route::middleware(['throttle:uploads'])->group(function () {2 Route::post('/audio', function () {3 // ...4 });5 6 Route::post('/video', function () {7 // ...8 });9});
Redisによるスロットリング
デフォルトでは、throttleミドルウェアはIlluminate\Routing\Middleware\ThrottleRequestsクラスにマップされます。ただし、アプリケーションのキャッシュドライバとしてRedisを使用している場合は、レート制限の管理にRedisを使用するようにLaravelに指示したい場合があります。そのためには、アプリケーションのbootstrap/app.phpファイルでthrottleWithRedisメソッドを使用する必要があります。このメソッドは、throttleミドルウェアをIlluminate\Routing\Middleware\ThrottleRequestsWithRedisミドルウェアクラスにマップします。
1->withMiddleware(function (Middleware $middleware) {2 $middleware->throttleWithRedis();3 // ...4})
フォームメソッド偽装
HTMLフォームはPUT、PATCH、DELETEアクションをサポートしていません。したがって、HTMLフォームから呼び出されるPUT、PATCH、DELETEルートを定義する場合は、フォームに非表示の_methodフィールドを追加する必要があります。_methodフィールドで送信された値が、HTTPリクエストメソッドとして使用されます。
1<form action="/example" method="POST">2 <input type="hidden" name="_method" value="PUT">3 <input type="hidden" name="_token" value="{{ csrf_token() }}">4</form>
便宜上、@method Bladeディレクティブを使用して、_method入力フィールドを生成できます。
1<form action="/example" method="POST">2 @method('PUT')3 @csrf4</form>
現在ルートへのアクセス
Routeファサードのcurrent、currentRouteName、currentRouteActionメソッドを使用して、受信リクエストを処理しているルートに関する情報にアクセスできます。
1use Illuminate\Support\Facades\Route;2 3$route = Route::current(); // Illuminate\Routing\Route4$name = Route::currentRouteName(); // string5$action = Route::currentRouteAction(); // string
ルータクラスとルートクラスで利用可能なすべてのメソッドを確認するには、Routeファサードの基底クラスとRouteインスタンスの両方のAPIドキュメントを参照してください。
Cross-Origin Resource Sharing (CORS)
Laravelは、設定した値でCORSのOPTIONS HTTPリクエストに自動的に応答できます。OPTIONSリクエストは、アプリケーションのグローバルミドルウェアスタックに自動的に含まれるHandleCors ミドルウェアによって自動的に処理されます。
場合によっては、アプリケーションのCORS設定値をカスタマイズする必要があります。config:publish Artisanコマンドを使用して、cors設定ファイルを公開することで、これを実行できます。
1php artisan config:publish cors
このコマンドは、アプリケーションのconfigディレクトリ内にcors.php設定ファイルを配置します。
CORSとCORSヘッダに関する詳細は、MDN WebドキュメントのCORSに関する記事を参照してください。
ルートキャッシュ
アプリケーションを本番環境にデプロイするときは、Laravelのルートキャッシュを利用する必要があります。ルートキャッシュを使用すると、アプリケーションのすべてのルートを登録するのにかかる時間が大幅に短縮されます。ルートキャッシュを生成するには、route:cache Artisanコマンドを実行します。
1php artisan route:cache
このコマンドを実行した後、キャッシュされたルートファイルはすべてのリクエストでロードされます。新しいルートを追加した場合は、新しいルートキャッシュを生成する必要があることに注意してください。このため、route:cacheコマンドはプロジェクトのデプロイ中にのみ実行する必要があります。
route:clearコマンドを使用して、ルートキャッシュをクリアできます。
1php artisan route:clear