Lang x Lang

Controllers

Table of Contents

Introduction

すべての request ハンドリングロジックを route ファイル内のクロージャとして定義する代わりに、この動作を controller クラスを使って整理することができます。コントローラは、関連する request ハンドリングロジックを single class にまとめることができます。たとえば、UserController class は、 users に関連するすべての着信リクエストを handle します。これには、表示、作成、更新、および deleting users が含まれます。 default では、コントローラはapp/Http/Controllersディレクトリに保存されます。

Writing Controllers

基本コントローラー

新しい controller を素早く作成するために、make:controllerという Artisan command を実行することができます。 default では、あなたの application に対するすべてのコントローラはapp/Http/Controllersディレクトリに保存されます:

php artisan make:controller UserController

基本的な controller の例を見てみましょう。 controller には、 HTTP requests に対応するための任意の数の public メソッドが存在するかもしれません:

<?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)
        ]);
    }
}

あなたが controller class と method を書き終えたら、以下のように controller method への route を定義することができます。

use App\Http\Controllers\UserController;

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

着信の request が指定された route URI と一致すると、App\Http\Controllers\UserController class のshow method が呼び出され、 route のパラメータが method に渡されます。

NOTE

コントローラーはrequiredとして基本の class を拡張する必要はありません。しかし、すべてのコントローラーで共有するべきメソッドを含む基本の controller class を拡張することは、時として便利です。

Single Action コントローラー

controller action が特に複雑な場合、その single action に専用の controller class を割り当てると便利かもしれません。これを達成するために、あなたは controller 内に single の__invoke method を定義することができます。

<?php

namespace App\Http\Controllers;

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

シングル action コントローラーのための routes を登録するとき、あなたはコントローラー method を指定する必要はありません。代わりに、あなたは単にコントローラーの名前をルーターに渡すことができます:

use App\Http\Controllers\ProvisionServer;

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

make:controller--invokableオプションを使用して、呼び出し可能な controller を生成することができます。これは Artisan command です。

php artisan make:controller ProvisionServer --invokable

NOTE

Controller スタブは、stub publishingを使用してカスタマイズすることができます。

Controller Middleware

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

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

または、あなたは controller class の中に middleware を指定する方が便利かもしれません。そのためには、あなたの controller はHasMiddlewareインタフェースを実装するべきです。これは、 controller が静的なmiddleware method を持つべきだと指示します。この method から、あなたはコントローラーのアクションに適用されるべき middleware の array を返すことができます。

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Routing\Controllers\HasMiddleware;
use Illuminate\Routing\Controllers\Middleware;

class UserController extends Controller 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']),
        ];
    }

    // ...
}

また、クロージャとして controller middleware を定義することも可能で、これは middleware class 全体を記述することなく、インラインの middleware を定義する便利な方法を提供します。

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);
        },
    ];
}

Resource Controllers

あなたがそれぞれの Eloquent model をあなたの application の" application "と考えるなら、それぞれの resource に対して同じ一連の操作を行うことが典型的です。例えば、あなたの application がPhotoの model とMovieの model を含んでいると想像してみてください。それらの resources を作成したり、読んだり、 update したり、 delete したりすることが users によくあります。

この一般的な使用例のために、 Laravel resource routing は、典型的な作成、読み取り、 update 、そして delete (CRUD) routes を controller に single の code ラインで割り当てます。始めるために、make:controller Artisan コマンドの--resourceオプションを使用して、これらのアクションを handle する controller をすばやく作成できます。

php artisan make:controller PhotoController --resource

この command は、app/Http/Controllers/PhotoController.phpに controller を生成します。 controller には、利用可能な resource 操作ごとに method が含まれます。次に、 controller を指す resource route を register することができます。

use App\Http\Controllers\PhotoController;

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

この single route declaration は、 resource 上のさまざまなアクションを handle するための複数の routes を作成します。生成された controller はすでに、これらのアクションそれぞれに対してスタブ化されたメソッドを持っています。覚えておいてください、あなたのアプリケーションの routes のクイックな概要はいつでも、route:list Artisan command を実行することで得ることができます。

あなたはresourcesの method に array を渡すことで、多くの resource コントローラーを一度に登録することもできます。

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

Resource Controllers によって処理されるアクション

動詞URIActionRoute 名前
GET/photosindexphotos.index
GET/photos/create作成するphotos.create
POST/photos保存photos.store
GET/photos/{photo}表示photos.show
GET/photos/{photo}/edit編集photos.edit
PUT/PATCH/photos/{photo}updatephotos.update
DELETE/photos/{photo}破壊photos.destroy

Model の不足挙動のカスタマイズ

通常、暗黙的にバインドされた resource model が見つからない場合、404 の HTTP response が生成されます。しかし、 resource route を定義する際に、missing method を呼び出すことで、この動作をカスタマイズすることができます。missing method は、リソースの routes のいずれかで暗黙的にバインドされた model が見つからない場合に呼び出されるクロージャを受け入れます:

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');
        });

ソフトデリートされた Models

通常、暗黙の model バインディングでは、 models がソフトデリートされたものは取得せず、代わりに 404 の HTTP response を返します。ただし、withTrashed method を呼び出して、 resource route を定義するときに、フレームワークにソフトデリートされた models を許可するよう指示することができます。

use App\Http\Controllers\PhotoController;

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

withTrashedを引数なしで呼び出すと、showedit、およびupdateの resource routes で軟らかく削除された models を有効にします。これらの routes の一部を指定したい場合は、withTrashedの method に array を渡すことができます:

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

Resource Model の指定

もしあなたが route model binding を使っていて、 resource コントローラーのメソッドが model インスタンスを型にヒントしたい場合、--model オプションを生成する際に controller に使用することができます。

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

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

resource controller を生成する際に、--requests オプションを提供することで、コントローラの storage および update メソッド用のform request クラス を Artisan が生成するように指示できます。

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

部分的な Resource Routes

resource route を宣言する際には、 controller が handle すべきアクションの一部を指定することができます。これは default アクションの全セットを指定する代わりに行います:

use App\Http\Controllers\PhotoController;

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

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

API Resource Routes

API によって消費される resource routes を宣言するとき、通常、createeditのような HTML テンプレートを表示する routes を除外したいと思うでしょう。便宜上、これら二つの routes を自動的に除外するためのapiResource method を使用することができます:

use App\Http\Controllers\PhotoController;

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

apiResources method に array を渡すことで、多くの APIresource コントローラーを一度に 登録することが可能です。

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

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

createeditmethod を含まない API resource controller をすばやく生成するには、make:controller command を実行する際に--apiスイッチを使用します:

php artisan make:controller PhotoController --api

ネストされた Resources

時折、ネストした resource に routes を定義する必要があります。例えば、写真 resource には複数の comments が添付されている場合があります。その resource controllers をネストさせるには、 route declaration において dot 表記を使用することができます。

use App\Http\Controllers\PhotoCommentController;

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

この route は、以下のような URI でアクセスできるネストされた resource を register します:

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

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

Laravel の暗黙の model バインディング 機能は、解決された子の model が親の model に所属していることを確認するようなネストされたバインディングを自動的に scope することができます。ネストされた resource を定義する際に scoped method を使用することで、自動的なスコープ化を有効にし、子の resource がどのフィールドによって取得されるべきかを Laravel に指示することもできます。これを達成する方法についての詳細は、リソース routes のスコープ化に関するドキュメンテーションをご覧ください。

浅いネスティング

よく、親と子の ID を両方とも URI に含める必要は全くない場合があります。なぜなら、子の ID はすでに unique な識別子となっているからです。自動インクリメントの primary keys のような unique な識別子を使用して URI セグメントで models を識別する場合、shallow nesting を使用することを選択できます。

use App\Http\Controllers\CommentController;

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

この route 定義は、次の routes を定義します:

動詞URIActionRoute 名前
GET/photos/{photo}/commentsインデックスphotos.comments.index
GET/photos/{photo}/comments/create作成するphotos.comments.create
POST/photos/{photo}/comments保存photos.comments.store
GET/comments/{comment}表示comments.show
GET/comments/{comment}/edit編集comments.edit
PUT/PATCH/comments/{comment}updatecomments.update
DELETE/comments/{comment}破壊comments.destroy

Resource Routes の命名

default では、すべての resource controller アクションには route 名が付いています。しかし、あなたはこれらの名前を上書きし、望ましい route 名をnames array で指定することができます:

use App\Http\Controllers\PhotoController;

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

Resource Route パラメータの命名

default"では、Route::resourceは "単数形"version の "resource" 名に基づいて "resourceroute" の "route" パラメータを作成します。これは、parameters "method"を使用して "resource"ごとに簡単に上書きできます。parameters "method"に渡される "array" は、"resource" 名とパラメータ名の関連 "array"であるべきです:

use App\Http\Controllers\AdminUserController;

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

上記の例では、リソースのshow route に対して次の URI が生成されます。

/users/{admin_user}

スコープ化 Resource Routes

Laravel の scoped implicit model binding feature は、解決された子の model が親の model に属することを確認するようにネストされたバインディングを自動的に scope することができます。ネストされた resource を定義するときに scoped method を使用することで、自動的なスコープが可能になり、子の resource がどのフィールドで retrieved されるべきかを Laravel に指示することができます。

use App\Http\Controllers\PhotoCommentController;

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

この route は、以下のような URI でアクセス可能なスコープ付きのネストされた resource を register します:

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

custom key の暗黙的なバインディングをネストした route パラメータとして使用すると、 Laravel は自動的に query を scope 化して、親の関係名を推測する規則を使用して親からネストした model を取得します。この場合、Photo model にはcommentsという関係名( route パラメータ名の複数形)が存在し、それを使用してComment model を取得できると想定されます。

Resource URI のローカライズ

default では、Route::resourceは英語の動詞と複数形のルールを使用して resource URI を作成します。createeditの action 動詞をローカライズする必要がある場合は、Route::resourceVerbs method を使用できます。これは、application のApp\Providers\AppServiceProvider内のboot method の最初に行うことができます。

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

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

/publicacion/crear

/publicacion/{publicaciones}/editar

Resource Controllers の補足

もし resource controller に対して追加の routes を default の resource routes セットを越えて追加する必要がある場合、それらの routes をRoute::resourceメソッドを呼び出す前に定義すべきです。そうしないと、resource method によって定義された routes が意図せずしてあなたの補足的な routes よりも優先されるかもしれません。

use App\Http\Controller\PhotoController;

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

NOTE

コントローラーは焦点を絞って運用してください。もし通常の resource アクションに含まれないメソッドを定期的に必要とする場合は、あなたの controller を 2 つの小さなコントローラーに分割することを検討してみてください。

Singleton Resource Controllers

時々、あなたの application は single インスタンスしか持たない resources を持つことがあります。例えば、user の profile は編集や更新ができますが、user は profile を複数持つことはできません。同様に、image は thumbnail を single だけ持つことができます。これらの resources は singleton resources と呼ばれ、resource のインスタンスが一つだけ存在するという意味です。このようなシナリオでは、singleton の resource controller を register することができます:

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

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

上記の singleton resource の定義は、以下の routes を register します。ご覧の通り、作成のための routes は singleton resources に対して登録されておらず、また、登録されている routes は、 resource のインスタンスが 1 つだけ存在するため、識別子を受け付けません。

動詞URIActionRoute 名称
GET/profile表示するprofile.show
GET/profile/edit編集profile.edit
PUT/PATCH/profileupdateprofile.update

Singleton resources も標準の resource 内にネストすることができます。

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

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

動詞URIActionRoute 名称
GET/photos/{photo}/thumbnail表示photos.thumbnail.show
GET/photos/{photo}/thumbnail/edit編集photos.thumbnail.edit
PUT/PATCH/photos/{photo}/thumbnailupdatephotos.thumbnail.update

作成可能な Singleton Resources

たまに、 singleton resource のための作成と storage routes を定義したくなるかもしれません。これを達成するために、 singleton resource route を登録する際にcreatable method を呼び出すことができます:

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

この例では、以下の routes が登録されます。ご覧の通り、作成可能な singleton resources に対してもDELETE route が登録されます。

動詞URIActionRoute 名前
GET/photos/{photo}/thumbnail/create作成するphotos.thumbnail.create
POST/photos/{photo}/thumbnail保存photos.thumbnail.store
GET/photos/{photo}/thumbnail表示photos.thumbnail.show
GET/photos/{photo}/thumbnail/edit編集photos.thumbnail.edit
PUT/PATCH/photos/{photo}/thumbnailupdatephotos.thumbnail.update
DELETE/photos/{photo}/thumbnail破壊photos.thumbnail.destroy

もし DELETE route を singleton resource に対して Laravel が register することを希望するが、作成または storage routes を register することは希望しない場合、destroyable method を活用することができます。

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

API Singleton Resources

apiSingleton method は、API 経由で操作されるシングルトン resource を登録するために使用できます。これにより、createおよびeditの routes が不要になります:

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

もちろん、 API singleton resources も creatable となり、その場合は store および destroy が resource の register および routes になる可能性があります。

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

Dependency Injection and Controllers

コンストラクタ注入

Laravel のservice containerはすべての Laravel コントローラを解決するために使用されます。その結果、あなたの controller のコンストラクタで必要な依存関係をすべて型ヒントすることが可能です。宣言された依存性は自動的に解決され、 controller インスタンスに注入されます。

<?php

namespace App\Http\Controllers;

use App\Repositories\UserRepository;

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

Method インジェクション

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

<?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');
    }
}

あなたの controller method も route パラメータからの input を期待している場合、他の依存関係の後に route の引数をリストします。例えば、あなたの route が以下のように定義されている場合:

use App\Http\Controllers\UserController;

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

あなたは依然としてIlluminate\Http\Requestに型ヒントを行い、定義することによってあなたのidパラメータにアクセスすることができます。その controller method は次のようになります:

<?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');
    }
}

当社サイトでは、Cookie を使用しています。各規約をご確認の上ご利用ください:
Cookie Policy, Privacy Policy および Terms of Use