メインコンテンツへスキップ

Documentation Index

Fetch the complete documentation index at: https://kawax.biz/llms.txt

Use this file to discover all available pages before exploring further.

Laravel 11 では「Slim Application Skeleton」としてアプリケーション構造が大幅に変わりました。旧構造のままアップグレードしたプロジェクトへ途中参加した場合や、Laravel 10 以前の書籍・チュートリアルで学習した場合に戸惑いやすい点をまとめています。Laravel 11 リリース当時にLaracastsのフォーラムやStack Overflowでよくされていた質問です。
この FAQ は新規プロジェクト(Laravel 11 以降)を対象としています。既存プロジェクトのアップグレード手順は移行ガイドを参照してください。
新構造では変更頻度の低い config ファイルがプロジェクトから削除されています。これらのファイルはフレームワーク内の config/ が使われます。プロジェクト側の config/ とフレームワーク側の config/ はマージされ、プロジェクト側が優先されます。カスタマイズが必要になった時点でファイルを作成すれば反映されます。
# フレームワーク内の config を確認する
cat vendor/laravel/framework/config/cors.php

# プロジェクト側にコピーしてカスタマイズする
php artisan config:publish cors
Laravel 11 の新構造では App\Http\Controllers\Controller が空のクラスになっており、Illuminate\Routing\Controller を継承せず、ValidatesRequests / AuthorizesRequests トレイトも使用していません。
Laravel 10Laravel 11
Illuminate\Routing\Controller を継承空のクラス
ValidatesRequests トレイト使用なし
AuthorizesRequests トレイト使用なし
参考: Laravel 10 の Controller vs Laravel 11 の Controller代替方法:
// $request->validate() を使う
public function store(Request $request)
{
    $validated = $request->validate([
        'title' => 'required|string|max:255',
    ]);
}

// Gate::authorize() を使う
use Illuminate\Support\Facades\Gate;

public function update(Request $request, Post $post)
{
    Gate::authorize('update', $post);
}
頻繁に使う場合は App\Http\Controllers\Controller を Laravel 10 と同様に戻す方法もあります。
<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;

abstract class Controller extends BaseController
{
    use AuthorizesRequests, ValidatesRequests;
}
新構造では app/Http/Kernel.php が廃止され、ミドルウェアの設定は bootstrap/app.phpwithMiddleware() で行います。
// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
    // TrustProxiesミドルウェアなどで設定していた項目はすべてMiddlewareクラスのメソッドで設定できます
    $middleware->trustProxies(at: '*');

    // グローバルミドルウェアの追加
    $middleware->append(\App\Http\Middleware\MyMiddleware::class);

    // ルートグループへのエイリアス設定
    $middleware->alias([
        'my-middleware' => \App\Http\Middleware\MyMiddleware::class,
    ]);

    // Web / API ミドルウェアグループのカスタマイズ
    $middleware->web(append: [
        \App\Http\Middleware\HandleInertiaRequests::class,
    ]);
})
カスタムミドルウェアのファイル自体は app/Http/Middleware/ に引き続き作成します。
$this->middleware()Illuminate\Routing\Controller の機能であり、新構造の空のベースコントローラーでは使えません。代わりに HasMiddleware インターフェースを実装して middleware() メソッドを定義します。
use Illuminate\Routing\Controllers\HasMiddleware;
use Illuminate\Routing\Controllers\Middleware;

class UserController extends Controller implements HasMiddleware
{
    public static function middleware(): array
    {
        return [
            'auth',
            new Middleware('log', only: ['index']),
            new Middleware('subscribed', except: ['index']),
        ];
    }
}
Laravel 13 以降では #[Middleware] Attribute も使用できます。
use Illuminate\Routing\Controllers\HasMiddleware;
use App\Http\Middleware\EnsureTokenIsValid;

#[Middleware(EnsureTokenIsValid::class)]
class UserController extends Controller
{
    // ...
}
参考: コントローラーミドルウェア
authorizeResource()AuthorizesRequests トレイトに依存しているため、新構造の空のベースコントローラーでは使えません。対応方法はいくつかあります。1. ベースコントローラーを Laravel 10 仕様に戻す(最も手軽)
// app/Http/Controllers/Controller.php
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Routing\Controller as BaseController;

abstract class Controller extends BaseController
{
    use AuthorizesRequests;
}
これにより $this->authorizeResource() が使えるようになります。2. Laravel 13 の #[Authorize] Attribute を各メソッドに付与する
use Illuminate\Routing\Attributes\Controllers\Authorize;
use App\Models\Post;

class PostController extends Controller
{
    #[Authorize('view', 'post')]
    public function show(Post $post) { /* ... */ }

    #[Authorize('update', 'post')]
    public function update(Request $request, Post $post) { /* ... */ }
}
新構造では app/Console/Kernel.php が廃止され、スケジュールの設定場所が変わりました。routes/console.php に記述する(推奨):
// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::command('emails:send')->daily();
Schedule::job(new SendEmails)->everyFiveMinutes();
bootstrap/app.php に記述する:
->withSchedule(function (Schedule $schedule) {
    $schedule->command('emails:send')->daily();
})
新構造では EventServiceProvider が廃止され、イベントとリスナーの手動登録が不要になりました。自動登録の仕組み: リスナークラスの handle() メソッドの引数にイベントクラスを型宣言すると自動で登録されます。
namespace App\Listeners;

use App\Events\OrderShipped;

class SendShipmentNotification
{
    // handle() の引数にイベントクラスを指定するだけで自動登録される
    public function handle(OrderShipped $event): void
    {
        // ...
    }
}
手動登録が必要な場合は AppServiceProvider::boot() で行います。
use Illuminate\Support\Facades\Event;

public function boot(): void
{
    Event::listen(
        OrderShipped::class,
        SendShipmentNotification::class,
    );
}
新構造では、サービスプロバイダーの一覧管理が config/app.php から bootstrap/providers.php に変わりました。
// bootstrap/providers.php
return [
    App\Providers\AppServiceProvider::class,
    App\Providers\MyCustomServiceProvider::class, // ← ここに追加
];
artisan make:provider で作成したプロバイダーは自動的にここへ追記されます。
新構造では app/Exceptions/Handler.php が廃止され、例外処理の設定は bootstrap/app.phpwithExceptions() で行います。
// bootstrap/app.php
->withExceptions(function (Exceptions $exceptions) {
    // 特定の例外をレポートしない
    $exceptions->dontReport(InvalidOrderException::class);

    // カスタムレンダリング
    $exceptions->render(function (InvalidOrderException $e, Request $request) {
        return response()->view('errors.invalid-order', status: 500);
    });

    // 未認証時のリダイレクト先変更
    $exceptions->shouldRenderJsonWhen(function (Request $request, Throwable $e) {
        return $request->is('api/*');
    });
})
ルートのカスタマイズは bootstrap/app.phpwithRouting() で行います。ルートファイルを追加する:
->withRouting(
    web: __DIR__.'/../routes/web.php',
    then: function () {
        Route::middleware('web')
            ->prefix('admin')
            ->group(base_path('routes/admin.php'));
    },
)
完全に制御する(Laravel 10 の RouteServiceProvider と同様):using を指定すると Laravel のデフォルトのルート登録が完全に無効になり、すべてを自分で制御できます。
->withRouting(
    using: function () {
        Route::middleware('web')
            ->group(base_path('routes/web.php'));

        Route::middleware('api')
            ->prefix('api')
            ->group(base_path('routes/api.php'));
    },
)
config/app.phpproviders キーを追加すると、フレームワーク内の config/app.php とマージされて反映されます。
// config/app.php
use Illuminate\Support\ServiceProvider;

return [
    // ...
    'providers' => ServiceProvider::defaultProviders()->replace([
        Illuminate\Foo\FooServiceProvider::class => Bar\BarServiceProvider::class,
    ])->toArray(),
];
replace() メソッドでデフォルトプロバイダーを独自実装に差し替えられます。
Laravel 11 以降、API 機能はデフォルトでは含まれておらず、必要な場合に個別インストールします。
php artisan install:api
このコマンドで以下が作成・設定されます。
  • routes/api.php
  • API 認証用の Laravel Sanctum の設定
  • bootstrap/app.php への API ルート登録
Laravel 11 以降、ブロードキャスト機能もデフォルトでは含まれておらず、必要な場合に個別インストールします。
php artisan install:broadcasting
このコマンドで以下が作成・設定されます。
  • routes/channels.php
  • Laravel Reverb のインストール設定
  • ブロードキャスト設定ファイル
bootstrap/app.php の内容を確認してください。Laravel 11 以降の新構造(または移行済み):
// bootstrap/app.php
return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(...)
    ->withMiddleware(...)
    ->withExceptions(...)
    ->create();
Laravel 10 以前の旧構造のままアップグレードしたプロジェクト:
// bootstrap/app.php
$app = new Illuminate\Foundation\Application(
    $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);

$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Http\Kernel::class
);
// ...
return Application::configure(... の形式なら新構造、そうでなければ旧構造のままアップグレードしたプロジェクトです。旧構造のプロジェクトを新構造に移行する手順は移行ガイドを参照してください。

関連ページ

Laravel 11以降のアプリケーション構造

新しいアプリケーション構造の全貌と ApplicationBuilder の内部実装を解説します。

旧構造から新構造への移行ガイド

Laravel 10 の旧アプリ構造から Laravel 11 以降の新構造へ移行する手順を解説します。
Last modified on May 3, 2026