メインコンテンツまでスキップ
バージョン: master

コントローラ (Controllers)

導入 (Introduction)

すべてのリクエスト処理ロジックをルート ファイル内のクロージャとして定義する代わりに、「コントローラ」クラスを使用してこの動作を整理したい場合があります。コントローラは、関連するリクエスト処理ロジックを 1 つのクラスにグループ化できます。たとえば、UserController クラスは、ユーザーの表示、作成、更新、削除など、ユーザーに関連するすべての受信リクエストを処理する場合があります。デフォルトでは、コントローラは app/Http/Controllers ディレクトリに保存されます。

コントローラの作成 (Writing Controllers)

基本的なコントローラ

新しいコントローラをすばやく生成するには、make:controller Artisan コマンドを実行します。デフォルトでは、アプリケーションのすべてのコントローラは app/Http/Controllers ディレクトリに保存されます。

php artisan make:controller UserController

基本的なコントローラの例を見てみましょう。コントローラには、受信した HTTP リクエストに応答するパブリック メソッドをいくつでも持つことができます。

<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\View\View;

class UserController extends Controller
{
/**
* Show the profile for a given user.
*/
public function show(string $id): View
{
return view('user.profile', [
'user' => User::findOrFail($id)
]);
}
}

コントローラのクラスとメソッドを作成したら、次のようにコントローラ メソッドへのルートを定義できます。

use App\Http\Controllers\UserController;

Route::get('/user/{id}', [UserController::class, 'show']);

受信リクエストが指定されたルート URI と一致すると、App\Http\Controllers\UserController クラスの show メソッドが呼び出され、ルート パラメーターがメソッドに渡されます。

コントローラは基本クラスを拡張するために必要ありません。ただし、すべてのコントローラで共有する必要があるメソッドを含む基本コントローラ クラスを拡張すると便利な場合があります。

シングルアクションコントローラ

コントローラのアクションが特に複雑な場合は、コントローラ クラス全体をその 1 つのアクション専用にすると便利な場合があります。これを実現するには、コントローラ内で単一の __invoke メソッドを定義します。

<?php

namespace App\Http\Controllers;

class ProvisionServer extends Controller
{
/**
* Provision a new web server.
*/
public function __invoke()
{
// ...
}
}

シングルアクションコントローラのルートを登録する場合、コントローラメソッドを指定する必要はありません。代わりに、単にコントローラの名前をルーターに渡すこともできます。

use App\Http\Controllers\ProvisionServer;

Route::post('/server', ProvisionServer::class);

make:controller Artisan コマンドの --invokable オプションを使用して、呼び出し可能なコントローラを生成できます。

php artisan make:controller ProvisionServer --invokable

コントローラ スタブは、スタブ発行 を使用してカスタマイズできます。

コントローラミドルウェア (Controller Middleware)

Middleware は、ルート ファイル内のコントローラのルートに割り当てることができます。

Route::get('/profile', [UserController::class, 'show'])->middleware('auth');

または、コントローラ クラス内でミドルウェアを指定すると便利な場合があります。これを行うには、コントローラは HasMiddleware インターフェイスを実装する必要があります。これは、コントローラが静的 middleware メソッドを持つ必要があることを指示します。このメソッドから、コントローラのアクションに適用するミドルウェアの配列を返すことができます。

<?php

namespace App\Http\Controllers;

use Illuminate\Routing\Controllers\HasMiddleware;
use Illuminate\Routing\Controllers\Middleware;

class UserController implements HasMiddleware
{
/**
* Get the middleware that should be assigned to the controller.
*/
public static function middleware(): array
{
return [
'auth',
new Middleware('log', only: ['index']),
new Middleware('subscribed', except: ['store']),
];
}

// ...
}

コントローラ ミドルウェアをクロージャーとして定義することもできます。これにより、ミドルウェア クラス全体を作成せずにインライン ミドルウェアを定義する便利な方法が提供されます。

use Closure;
use Illuminate\Http\Request;

/**
* Get the middleware that should be assigned to the controller.
*/
public static function middleware(): array
{
return [
function (Request $request, Closure $next) {
return $next($request);
},
];
}

ミドルウェアの属性

PHP 属性を使用してミドルウェアをコントローラに割り当てることもできます。

<?php

namespace App\Http\Controllers;

use Illuminate\Routing\Attributes\Controllers\Middleware;

#[Middleware('auth')]
#[Middleware('log', only: ['index'])]
#[Middleware('subscribed', except: ['store'])]
class UserController
{
// ...
}

ミドルウェア属性を個々のコントローラ メソッドに配置することもできます。メソッドに割り当てられたミドルウェアは、クラス レベルで割り当てられたミドルウェアとマージされます。

<?php

namespace App\Http\Controllers;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Routing\Attributes\Controllers\Middleware;

#[Middleware('auth')]
class UserController
{
#[Middleware('log')]
#[Middleware('subscribed')]
public function index()
{
// ...
}

#[Middleware(static function (Request $request, Closure $next) {
// ...

return $next($request);
})]
public function store()
{
// ...
}
}

リソースコントローラ (Resource Controllers)

アプリケーション内の各 Eloquent モデルを「リソース」と考えると、アプリケーション内の各リソースに対して同じ一連のアクションを実行するのが一般的です。たとえば、アプリケーションに Photo モデルと Movie モデルが含まれていると想像してください。ユーザーはこれらのリソースを作成、読み取り、更新、または削除できる可能性があります。

この一般的なユースケースのため、Laravel リソースルーティングは、1 行のコードで典型的な作成、読み取り、更新、および削除 (「CRUD」) ルートをコントローラに割り当てます。まず、make:controller Artisan コマンドの --resource オプションを使用して、これらのアクションを処理するコントローラをすばやく作成できます。

php artisan make:controller PhotoController --resource

このコマンドは、app/Http/Controllers/PhotoController.php にコントローラを生成します。コントローラには、使用可能なリソース操作ごとにメソッドが含まれます。次に、コントローラを指すリソース ルートを登録できます。

use App\Http\Controllers\PhotoController;

Route::resource('photos', PhotoController::class);

この 1 つのルート宣言により、リソースに対するさまざまなアクションを処理するための複数のルートが作成されます。生成されたコントローラには、これらのアクションごとにスタブ化されたメソッドがすでに含まれています。 route:list Artisan コマンドを実行すると、アプリケーションのルートの概要をいつでも簡単に取得できることに注意してください。

配列を resources メソッドに渡すことで、多くのリソース コントローラを一度に登録することもできます。

Route::resources([
'photos' => PhotoController::class,
'posts' => PostController::class,
]);

softDeletableResources メソッドは、すべて withTrashed メソッドを使用する多くのリソース コントローラを登録します。

Route::softDeletableResources([
'photos' => PhotoController::class,
'posts' => PostController::class,
]);

リソースコントローラによって処理されるアクション

動詞URIアクション路線名
得る/photos索引写真.インデックス
得る/photos/create作成する写真.作成
役職/photos写真.ストア
得る/photos/{photo}見せる写真.ショー
得る/photos/{photo}/edit編集写真.編集
パット/パッチ/photos/{photo}アップデート写真.更新
消去/photos/{photo}破壊する写真.破壊

欠落モデルの動作のカスタマイズ

通常、暗黙的にバインドされたリソース モデルが見つからない場合は、404 HTTP 応答が生成されます。ただし、リソース ルートを定義するときに missing メソッドを呼び出すことで、この動作をカスタマイズできます。 missing メソッドは、リソースのルートのいずれにも暗黙的にバインドされたモデルが見つからない場合に呼び出されるクロージャを受け入れます。

use App\Http\Controllers\PhotoController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;

Route::resource('photos', PhotoController::class)
->missing(function (Request $request) {
return Redirect::route('photos.index');
});

ソフト削除されたモデル

通常、暗黙的なモデル バインディングでは、ソフト削除されました になったモデルは取得されず、代わりに 404 HTTP 応答が返されます。ただし、リソース ルートを定義するときに withTrashed メソッドを呼び出すことで、論理的に削除されたモデルを許可するようにフレームワークに指示できます。

use App\Http\Controllers\PhotoController;

Route::resource('photos', PhotoController::class)->withTrashed();

引数なしで withTrashed を呼び出すと、showedit、および update リソース ルートの論理的に削除されたモデルが許可されます。配列を withTrashed メソッドに渡すことで、これらのルートのサブセットを指定できます。

Route::resource('photos', PhotoController::class)->withTrashed(['show']);

リソースモデルの指定

ルートモデルバインディング を使用していて、リソース コントローラのメソッドでモデル インスタンスのタイプヒントを取得したい場合は、コントローラの生成時に --model オプションを使用できます。

php artisan make:controller PhotoController --model=Photo --resource

フォームリクエストの生成

リソース コントローラを生成するときに --requests オプションを指定して、コントローラのストレージおよび更新メソッドに対して フォームリクエストクラス を生成するように Artisan に指示できます。

php artisan make:controller PhotoController --model=Photo --resource --requests

部分的なリソースルート

リソース ルートを宣言するとき、デフォルト アクションの完全なセットの代わりに、コントローラが処理する必要があるアクションのサブセットを指定できます。

use App\Http\Controllers\PhotoController;

Route::resource('photos', PhotoController::class)->only([
'index', 'show'
]);

Route::resource('photos', PhotoController::class)->except([
'create', 'store', 'update', 'destroy'
]);

APIリソースルート

API によって使用されるリソース ルートを宣言する場合、一般的に、createedit などの HTML テンプレートを提示するルートを除外する必要があります。便宜上、apiResource メソッドを使用して、これら 2 つのルートを自動的に除外できます。

use App\Http\Controllers\PhotoController;

Route::apiResource('photos', PhotoController::class);

配列を apiResources メソッドに渡すことで、多くの API リソース コントローラを一度に登録できます。

use App\Http\Controllers\PhotoController;
use App\Http\Controllers\PostController;

Route::apiResources([
'photos' => PhotoController::class,
'posts' => PostController::class,
]);

create メソッドまたは edit メソッドを含まない API リソース コントローラを迅速に生成するには、make:controller コマンドの実行時に --api スイッチを使用します。

php artisan make:controller PhotoController --api

ネストされたリソース

場合によっては、ネストされたリソースへのルートを定義する必要があるかもしれません。たとえば、写真リソースには、写真に添付できる複数のコメントがある場合があります。リソース コントローラをネストするには、ルート宣言で「ドット」表記を使用できます。

use App\Http\Controllers\PhotoCommentController;

Route::resource('photos.comments', PhotoCommentController::class);

このルートは、次のような URI でアクセスできるネストされたリソースを登録します。

/photos/{photo}/comments/{comment}

ネストされたリソースのスコープ設定

Laravel の 暗黙的なモデルバインディング 機能は、解決された子モデルが親モデルに属していることが確認されるように、ネストされたバインディングを自動的にスコープ設定できます。ネストされたリソースを定義するときに scoped メソッドを使用すると、自動スコープを有効にしたり、子リソースを取得するフィールドを Laravel に指示したりできます。これを実現する方法の詳細については、リソースルートのスコープ設定 のドキュメントを参照してください。

浅いネスティング

多くの場合、子 ID はすでに一意の識別子であるため、URI 内に親 ID と子 ID の両方を含める必要は必ずしもありません。自動インクリメント主キーなどの一意の識別子を使用して URI セグメント内のモデルを識別する場合、「浅いネスト」の使用を選択できます。

use App\Http\Controllers\CommentController;

Route::resource('photos.comments', CommentController::class)->shallow();

このルート定義では、次のルートが定義されます。

動詞URIアクション路線名
得る/photos/{photo}/comments索引写真.コメント.インデックス
得る/photos/{photo}/comments/create作成する写真.コメント.作成
役職/photos/{photo}/comments写真.コメント.ストア
得る/comments/{comment}見せるコメント.ショー
得る/comments/{comment}/edit編集コメント.編集
パット/パッチ/comments/{comment}アップデートコメント.更新
消去/comments/{comment}破壊するコメント.破壊

リソースルートの命名

デフォルトでは、すべてのリソース コントローラ アクションにはルート名が付いています。ただし、希望のルート名を含む names 配列を渡すことで、これらの名前をオーバーライドできます。

use App\Http\Controllers\PhotoController;

Route::resource('photos', PhotoController::class)->names([
'create' => 'photos.build'
]);

リソースルートパラメータの命名

デフォルトでは、Route::resource はリソース名の「単数化」バージョンに基づいてリソース ルートのルート パラメーターを作成します。これは、parameters メソッドを使用してリソースごとに簡単にオーバーライドできます。 parameters メソッドに渡される配列は、リソース名とパラメーター名の連想配列である必要があります。

use App\Http\Controllers\AdminUserController;

Route::resource('users', AdminUserController::class)->parameters([
'users' => 'admin_user'
]);

上記の例では、リソースの show ルートに対して次の URI を生成します。

/users/{admin_user}

リソースルートのスコープ設定

Laravel の スコープ指定された暗黙的なモデル バインディング 機能は、解決された子モデルが親モデルに属していることが確認されるように、ネストされたバインディングを自動的にスコープ設定できます。ネストされたリソースを定義するときに scoped メソッドを使用すると、自動スコープを有効にしたり、子リソースを取得するフィールドを Laravel に指示したりできます。

use App\Http\Controllers\PhotoCommentController;

Route::resource('photos.comments', PhotoCommentController::class)->scoped([
'comment' => 'slug',
]);

このルートは、次のような URI でアクセスできるスコープ付きのネストされたリソースを登録します。

/photos/{photo}/comments/{comment:slug}

カスタムのキー付き暗黙的バインディングをネストされたルートパラメーターとして使用する場合、Laravel は、親の関係名を推測する規則を使用して、親によってネストされたモデルを取得するためにクエリのスコープを自動的に設定します。この場合、Photo モデルには、Comment モデルを取得するために使用できる comments (ルート パラメーター名の複数形) という名前のリレーションシップがあると想定されます。

リソース URI のローカライズ

デフォルトでは、Route::resource は英語の動詞と複数形ルールを使用してリソース URI を作成します。 create および edit アクション動詞をローカライズする必要がある場合は、Route::resourceVerbs メソッドを使用できます。これは、アプリケーションの App\Providers\AppServiceProvider 内の boot メソッドの先頭で行うことができます。

/**
* Bootstrap any application services.
*/
public function boot(): void
{
Route::resourceVerbs([
'create' => 'crear',
'edit' => 'editar',
]);
}

Laravelのpluralizerはニーズに基づいて構成できるいくつかの異なる言語をサポートしています。動詞と複数形言語をカスタマイズすると、Route::resource('publicacion', PublicacionController::class) などのリソース ルート登録によって次の URI が生成されます。

/publicacion/crear

/publicacion/{publicaciones}/editar

リソースコントローラの補足

リソース ルートのデフォルト セットを超えて追加のルートをリソース コントローラに追加する必要がある場合は、Route::resource メソッドを呼び出す前にそれらのルートを定義する必要があります。そうしないと、resource メソッドで定義されたルートが、補助ルートよりも意図せず優先される可能性があります。

use App\Http\Controller\PhotoController;

Route::get('/photos/popular', [PhotoController::class, 'popular']);
Route::resource('photos', PhotoController::class);

コントローラに集中することを忘れないでください。一般的なリソース アクションのセット以外のメソッドが日常的に必要な場合は、コントローラを 2 つの小さなコントローラに分割することを検討してください。

シングルトンリソースコントローラ

場合によっては、アプリケーションにインスタンスが 1 つしかないリソースが存在することがあります。たとえば、ユーザーの「プロフィール」は編集または更新できますが、ユーザーは複数の「プロフィール」を持つことはできません。同様に、画像には 1 つの「サムネイル」が含まれる場合があります。これらのリソースは「シングルトン リソース」と呼ばれます。これは、リソースのインスタンスが 1 つだけ存在できることを意味します。これらのシナリオでは、「シングルトン」リソース コントローラを登録できます。

use App\Http\Controllers\ProfileController;
use Illuminate\Support\Facades\Route;

Route::singleton('profile', ProfileController::class);

上記のシングルトン リソース定義により、次のルートが登録されます。ご覧のとおり、「作成」ルートはシングルトン リソースには登録されておらず、リソースのインスタンスは 1 つしか存在しないため、登録されたルートは識別子を受け入れません。

動詞URIアクション路線名
得る/profile見せるプロフィール.ショー
得る/profile/edit編集プロフィール.編集
パット/パッチ/profileアップデートプロフィール.更新

シングルトン リソースは、標準リソース内にネストすることもできます。

Route::singleton('photos.thumbnail', ThumbnailController::class);

この例では、photos リソースはすべての 標準リソースルート を受け取ります。ただし、thumbnail リソースは、次のルートを持つシングルトン リソースになります。

動詞URIアクション路線名
得る/photos/{photo}/thumbnail見せる写真.サムネイル.ショー
得る/photos/{photo}/thumbnail/edit編集写真.サムネイル.編集
パット/パッチ/photos/{photo}/thumbnailアップデート写真.サムネイル.更新

作成可能なシングルトン リソース

場合によっては、シングルトン リソースの作成ルートと保存ルートを定義することが必要になる場合があります。これを実現するには、シングルトン リソース ルートを登録するときに creatable メソッドを呼び出すことができます。

Route::singleton('photos.thumbnail', ThumbnailController::class)->creatable();

この例では、以下の経路が登録されます。ご覧のとおり、DELETE ルートも作成可能なシングルトン リソースに登録されます。

動詞URIアクション路線名
得る/photos/{photo}/thumbnail/create作成する写真.サムネイル.作成
役職/photos/{photo}/thumbnail写真.サムネイル.ストア
得る/photos/{photo}/thumbnail見せる写真.サムネイル.ショー
得る/photos/{photo}/thumbnail/edit編集写真.サムネイル.編集
パット/パッチ/photos/{photo}/thumbnailアップデート写真.サムネイル.更新
消去/photos/{photo}/thumbnail破壊する写真.サムネイル.破壊

Laravel にシングルトン リソースの DELETE ルートを登録させたいが、作成ルートやストレージ ルートは登録しない場合は、destroyable メソッドを利用できます。

Route::singleton(...)->destroyable();

APIシングルトンリソース

apiSingleton メソッドは、API 経由で操作されるシングルトン リソースを登録するために使用できます。これにより、create ルートと edit ルートが不要になります。

Route::apiSingleton('profile', ProfileController::class);

もちろん、API シングルトン リソースは creatable である場合もあります。これにより、リソースの store ルートと destroy ルートが登録されます。

Route::apiSingleton('photos.thumbnail', ProfileController::class)->creatable();

ミドルウェアとリソースコントローラ

Laravel では、middlewaremiddlewareFor、および withoutMiddlewareFor メソッドを使用して、リソース ルートのすべてのメソッドまたは特定のメソッドのみにミドルウェアを割り当てることができます。これらのメソッドは、各リソース アクションにどのミドルウェアを適用するかをきめ細かく制御できます。

すべてのメソッドにミドルウェアを適用する

middleware メソッドを使用して、リソースまたはシングルトン リソース ルートによって生成されたすべてのルートにミドルウェアを割り当てることができます。

Route::resource('users', UserController::class)
->middleware(['auth', 'verified']);

Route::singleton('profile', ProfileController::class)
->middleware('auth');

特定のメソッドへのミドルウェアの適用

middlewareFor メソッドを使用して、特定のリソース コントローラの 1 つ以上の特定のメソッドにミドルウェアを割り当てることができます。

Route::resource('users', UserController::class)
->middlewareFor('show', 'auth');

Route::apiResource('users', UserController::class)
->middlewareFor(['show', 'update'], 'auth');

Route::resource('users', UserController::class)
->middlewareFor('show', 'auth')
->middlewareFor('update', 'auth');

Route::apiResource('users', UserController::class)
->middlewareFor(['show', 'update'], ['auth', 'verified']);

middlewareFor メソッドは、シングルトンおよび API シングルトン リソース コントローラと組み合わせて使用​​することもできます。

Route::singleton('profile', ProfileController::class)
->middlewareFor('show', 'auth');

Route::apiSingleton('profile', ProfileController::class)
->middlewareFor(['show', 'update'], 'auth');

特定のメソッドからミドルウェアを除外する

withoutMiddlewareFor メソッドを使用して、リソース コントローラの特定のメソッドからミドルウェアを除外できます。

Route::middleware(['auth', 'verified', 'subscribed'])->group(function () {
Route::resource('users', UserController::class)
->withoutMiddlewareFor('index', ['auth', 'verified'])
->withoutMiddlewareFor(['create', 'store'], 'verified')
->withoutMiddlewareFor('destroy', 'subscribed');
});

依存関係の注入とコントローラ (Dependency Injection and Controllers)

コンストラクターのインジェクション

Laravel サービスコンテナ は、すべての Laravel コントローラを解決するために使用されます。その結果、コントローラがコンストラクターで必要とする依存関係をタイプヒントで指定できるようになります。宣言された依存関係は自動的に解決され、コントローラ インスタンスに挿入されます。

<?php

namespace App\Http\Controllers;

use App\Repositories\UserRepository;

class UserController extends Controller
{
/**
* Create a new controller instance.
*/
public function __construct(
protected UserRepository $users,
) {}
}

メソッドインジェクション

コンストラクターのインジェクションに加えて、コントローラのメソッドに対するタイプヒントの依存関係を指定することもできます。メソッド インジェクションの一般的な使用例は、コントローラ メソッドに Illuminate\Http\Request インスタンスを挿入することです。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class UserController extends Controller
{
/**
* Store a new user.
*/
public function store(Request $request): RedirectResponse
{
$name = $request->name;

// Store the user...

return redirect('/users');
}
}

コントローラ メソッドがルート パラメーターからの入力も期待している場合は、他の依存関係の後にルート引数をリストします。たとえば、ルートが次のように定義されているとします。

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
{
/**
* Update the given user.
*/
public function update(Request $request, string $id): RedirectResponse
{
// Update the user...

return redirect('/users');
}
}