基礎から学ぶLaravelを読みながらLaravel11を触ってみたときのメモ

 佐野大樹『基礎から学ぶLaravel』C&R研究所 2003を読み進めながら、Laravel11を触ってみたときに躓いたポイントがたくさんあったのでその個所と解決方法やそれが書いてあるサイトのリンクをここに記す。前提条件として、この書籍ではLaravel Sailによる環境構築を行っている。

p.31 プロジェクト作成後、Laravelのトップページが表示されない

 sailコマンドを実行してアプリケーションを起動した後、http://localhostにアクセスしてもLaravelのトップページが表示されず、Apache2 Default Pageが表示されてしまう。

解決方法

 Apache2が起動していることが原因なので、コマンドで停止することでLaravelのトップページが表示される。なぜApache2が起動してしまうのかは分からない。

p.79, p.241 Laravel11のモデルにはuse HasFactory;の記述がない

 Laravel11でartisanコマンドヲ使ってモデルクラスを作成してもクラス内にuseHasFactory;の記述がないので、シーダーファイルを作成してファクトリ機能を使ってもレコードを生成することができない。

解決方法

 シーダーファイルと紐づいているモデルクラスでファクトリ機能を読み込む必要がある。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Str;

class Book extends Model
{
    use HasFactory;

p.248 app/Http/Middleware/Authenticate.phpが存在しない

 Laravel11ではauthミドルウェアに関連するファイルとしてapp/Http/Middleware/Authenticate.phpが存在せず、bootstrap/app.phpに記述する必要がある。

解決方法

 実際のboostrap/app.phpには以下のように記述した。

<?php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Middleware\AccessLogger;
use App\Providers\DatabaseServiceProvider;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        
        // 非ログインユーザー用のリダイレクト設定
        $middleware->redirectGuestsTo(function (Request $request) {
            // パスがadmin/から始まる場合、管理者ログイン画面へリダイレクト
            if ($request->is('admin/*')) {
                return route('admin.create');
            }
    
            // そうでない場合は一般ユーザーログイン画面へリダイレクト
            return route('login');
        });

        // ログインユーザー用のリダイレクト設定
        $middleware->redirectUsersTo(function () {

            // 管理者だった場合、書籍一覧画面へリダイレクト
            if (Auth::guard('admin')->check()) {
                return route('book.index');
            }

            // 一般ユーザーだった場合はダッシュボードへリダイレクト
            return route('dashboard');
        });

        $middleware->append(AccessLogger::class);

    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

p.265 app/Http/Kernel.phpが存在しない

 Laravel11ではapp/Http/Kernel.phpファイルが存在しないので、グローバルミドルウェアを登録する場合はbootstrap/app.phpに記述する必要がある。

解決方法

<?php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Middleware\AccessLogger;
use App\Providers\DatabaseServiceProvider;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        
        // 非ログインユーザー用のリダイレクト設定
        $middleware->redirectGuestsTo(function (Request $request) {
            // パスがadmin/から始まる場合、管理者ログイン画面へリダイレクト
            if ($request->is('admin/*')) {
                return route('admin.create');
            }
    
            // そうでない場合は一般ユーザーログイン画面へリダイレクト
            return route('login');
        });

        // ログインユーザー用のリダイレクト設定
        $middleware->redirectUsersTo(function () {

            // 管理者だった場合、書籍一覧画面へリダイレクト
            if (Auth::guard('admin')->check()) {
                return route('book.index');
            }

            // 一般ユーザーだった場合はダッシュボードへリダイレクト
            return route('dashboard');
        });

        $middleware->append(AccessLogger::class);

    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

p.293 Auth::user()->cannot()を使うとエディターで警告が出る

 Visual Studio Codeを使っていると Auth::user()->cannnot(‘update’, $book) のコードに対して cannot メソッドの部分で『Undefined method ‘cannot’』と警告が出る。ChatGPTで調べた結果、エディターが Auth::user() の戻り値が必ず null ではないと理解できていない可能性があり、Auth::user() が null を返すケースを考慮して、null もしくは User クラスのインスタンスが返ってくると解釈しているらしい。Auth::user() が返すインスタンスが Authenticatable インターフェースを実装している User クラスであることを理解できない、もしくは cannot メソッドの存在を把握できていないときに出ることが多いようだ。

解決方法

 ChatGPTが提案した解決方法として 、以下の方法があるので両方採用する。

  • ?-> 演算子を使用する
  • PHPDocコメントで型を明示

 理由として、?-> 演算子を使っただけでは警告が消えないこと、PHPDocコメントで型を明示しただけでは Auth::user() が null だった時に『Call to a member function cannot() on null』エラーが返ってくることが挙げられる。PHP8では ?-> 演算子を使うことでオブジェクトが null の場合にメソッドの呼び出しを避けることができるので、組み合わせることが最善の方法だと判断した。

// 作成者以外はアクセス不可
/** @var \App\Models\User $user */
$user = Auth::user();

if ($user?->cannot('update', $book)) {
    abort(403);
}

 

p.302, 308 authorizeResource does not exist.エラーが出る

解決方法

 Laravel10ではControllerクラスは use Illuminate\Routing\Controller as BaseController; でBaseController を継承しているのだが、Laravel11ではControllerクラスは何も継承していないので、 \Illuminate\Routing\Controller を継承し、use AuthorizesRequests; を追記すればよい。

<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Auth\Access\AuthorizesRequests;

abstract class Controller extends \Illuminate\Routing\Controller
{
    //
    use AuthorizesRequests;
}

p.307 ゲートの定義先

 Laravel10ではゲートの定義は app/Providers/AuthServiceProvider.php で行うが、Laravel11にはそのファイルが存在しない。

解決方法

 Laravel11ではAppServiceProvider.php で定義を行う。

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Gate;
use App\Models\Admin;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        //
        Gate::define('example-com-user', function (Admin $admin) {
            // IDのドメインがexample.comかどうか
            return substr($admin->login_id, -11) === 'example.com';
        });
    }
}

p.357 routes/api.phpが存在しない

 Laravel10には存在していた routes/api.php ファイルがLaravel11には存在していないので作成する必要がある。

解決方法

 コンソールでsail artisan install:api コマンドを入力して routes/api.php ファイルを作成する。

コメント

タイトルとURLをコピーしました