Laravel 11.xがリリースされてから暫く経過していますが、やっと手持ちのLaravel 10.xのプロジェクトの更新作業に取り掛かっています。今回もLaravel Shiftのサービスを使用していますが、Laravel 10.xからLaravel11.xへの更新をすべて自動で行ってくれるわけではないです。

しかし、Laravelのサイトで説明されている更新のステップのドキュメンテーションを読むよりは、具体的な更新の変更がヒントとなり役に立ちます。もちろんShiftの変更はそれだけ十分というレベルからは遠く、とりわけ今回の更新では構造的に大きなLaravelの変更があるので、Shiftの変更後は確認とともに手動の編集作業が必須となります。

ここではお客さんのプロジェクトでの更新で私が苦労した部分をいくつか説明しますが、過去の記事Laravel 11.xのインストールについても説明があるので合わせてお読みください。

configのファイルたちの復元

Laravel Shiftを使用した後に、config/ディレクトリ下のいくつかのファイルが削除あるいは編集されてることに気づきます。

実際、Laravel 10.xLaravel 11.xの両方で新規のプロジェクト作成して比較してみると、以下のファイルがLaravel 11.xでは削除されています。フレームワークのスリム化の一環だそうです。

config/broadcasting.php
config/cors.php
config/hashing.php
config/sanctum.php
config/view.php

最初は、config/以下のすべてのファイルを削除するという案もあったそうですが、Laravelの作者のTaylor氏は夜寝れないほど悩んで、使用される頻度が少ない上のファイルの削除となったそうです。確かに小さいプロジェクトではそれらは使用することはなさそうです。

また、tinkerで上で削除されているconfig/view.phpの設定を見ると、

> config('view')
= [
    "paths" => [
      "/var/www/repos/laravel-11x/resources/views",
    ],
    "compiled" => "/var/www/repos/laravel-11x/storage/framework/views",
  ]

と設定ファイルがないのに裏ではしっかりデフォルトが設定されています。

さて、私のお客さんのプロジェクトでShiftを使用してLaravel 11.xに更新後では、以下のファイルが削除されていました。

config/broadcasting.php
config/cache.php
config/cors.php
config/hashing.php
config/queue.php
config/session.php
config/view.php

先のLaravel 11.xのデフォルトのプロジェクトと違って、cache.phpやqueue.phpやsession.phpも削除されています。さらに、残ったconfig/app.phpとかでは今まで存在したコメントを含めてほとんどの中身が削除されています。

基本的に、ShiftはLaravel10.xのデフォルトと同じ中身なら削除、差分があるなら差分だけと残すという方針なのでしょう。先に説明したように、設定ファイルがないからと言ってその設定が存在しなわけではないのです。.envの値もチェックしてLaravelでは以前と同様に実行時には設定値の値をメモリーに設定します。

しかし、プロジェクトを管理する上で、裏で隠されているのは理解しにくいです。ということで私は手動でShiftで削除や編集されたファイルを復元することに決めました。

戻す作業は簡単。

$ php artisan config:publish 

と実行すると、以下のようなメニューが表示されます。

そこで戻したいファイルを選択して戻すことができます。

しかし、すでに存在するファイルを戻したいなら、

$ php artisan config:publish --force

として実行するとすでに存在ファイルが上書きされます。

ベストは、Laravel 11.xの新規プロジェクトを他のディレクトリで作成して、そこでconfig:publishを実行してデフォルトのファイルを書き出し、それとあなたのプロジェクトのLaravel 11.x更新前のファイルと比較しながら変更することをお勧めします。

そのためには、

$ php artisan config:publish --all --force

を実行するのが良いです。

せっかくスリムになったのに設定ファイルを戻すのはプログラムのパフォーマンスに影響を与えるのでは?と思うかもしれません。
しかし、本番環境では、以下の実行して最適化のキャッシュファイルを作成すればそのような心配の必要ないです。

$ php artisan config:cache

.envを変更する必要がある

config/のファイルを復元して、じみちに以前のファイルと比較して、以前に編集したconfigファイルを戻したりするのですが、そこで気づくのは、Laravel 11.xでは、環境変数の名前が変わっている、設定ファイルの環境変数のデフォルト値が変わっている、そして、以前は.envで設定できなかった環境変数が設定できるようになっていることです。

お客さんのプロジェクトでは、以下の値の.envへの追加あるいは編集となりました(+は追加、ーは削除)。大半は以前.envで編集では設定できずにconfig/のファイルを編集していたので、良い変更かもしれません。

# config/app.phpでの変更により以前.envで設定できない環境変数ができるようになった
+APP_TIMEZONE=Asia/Tokyo
+APP_LOCALE=ja
+APP_FAKER_LOCALE=ja_JP

# config/auth.phpでの変更により.envで設定できない環境変数ができるようになった
+AUTH_GUARD=admin
+AUTH_PASSWORD_BROKER=admin

# config/cache.phpでの変更により環境変数名が変わった
-CACHE_DRIVER=file
+CACHE_STORE=file

# config/database.phpでの変更により環境変数のデフォルト値が変わった、また.envで設定できない環境変数ができるようになった
+DB_CONNECTION=mysql
+DB_CHARSET=utf8mb3
+DB_COLLATION=utf8mb3_general_ci
+REDIS_CLIENT=predis

# config/logging.phpでの変更により.envで設定できない環境変数ができるようになった
+LOG_STACK=single

# config/session.phppでの変更により.envで設定できない環境変数ができるようになった
+SESSION_EXPIRE_ON_CLOSE=false

削除されたEventServiceProviderの中身の行方

フレームワークのスリム化として、app/Providers/のファイルの統合化があります。その結果削除されたProviderの1つにEventServiceProvider.phpがあります。

私のお客さんのプロジェクトでは以前は、EventServiceProvider.phpにおいて、以下のようなイベントとリスナーのマップが設定されていました。

...
class EventServiceProvider extends ServiceProvider
{
namespace App\Providers;

use App\Events\SanctumUnauthenticated;
use App\Listeners\CommandFinishedListener;
use App\Listeners\CommandStartingListener;
use App\Listeners\LoginListener;
use App\Listeners\LogoutListener;
use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
use Illuminate\Console\Events\CommandFinished;
use Illuminate\Console\Events\CommandStarting;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */

    protected $listen = [
        SanctumUnauthenticated::class  => [
            SecureLogging::class,
        ],
        Login::class  => [
            LoginListener::class,
        ],
        Logout::class  => [
            LogoutListener::class,
        ],
        CommandStarting::class => [
            CommandStartingListener::class,
        ],
        CommandFinished::class => [
            CommandFinishedListener::class,
        ],
    ];"
...

Laravel 11.xの更新でEventServiceProvider.phpが削除された後には、上のマップを以下のように、AppServiceProviderにおいてEvent::listenのクロージャで設定可能となります。しかし、Shiftのサービスではこの自動変換は行われずに、PRでの説明だけとなっておりこの部分はとても頼りにならず、手動の編集が必要となります。


namespace App\Providers;

use App\Events\SanctumUnauthenticated;
use App\Listeners\CommandFinishedListener;
use App\Listeners\CommandStartingListener;
use App\Listeners\LoginListener;
use App\Listeners\LogoutListener;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Event::listen(
            SanctumUnauthenticated::class,
            CommandFinishedListener::class,
            CommandStartingListener::class,
            LoginListener::class,
            LogoutListener::class,
        );
    }
...

しかし、app/Events/app/Listeners/で定義したイベントやリスナーをいちいちリストするのは面倒です。

もっと簡単なのは、bootstra/app.phpにおいて、Laravelに見つけてもらうことです。

...
return Application::configure(basePath: dirname(__DIR__))
    ->withProviders()
...
   ->withEvents(discover: [
        __DIR__.'/../app/Events',
        __DIR__.'/../app/Listeners',
        __DIR__.'/../app/Modules/Pmaster/Listeners',
    ])
...

このように、withEvents()で必要なディレクトリーを指定するだけです。将来に追加や削除しても自動でdiscoverされます。

正しくdiscoverされているかを確認するには、以下のコマンドを実行します。

$ php artisan event:list

そして、本番環境では、以下を実行して先のcacheと同様に必要データをキャッシュします。

$ php artisan event:cache

最後に

Laravel 11.xへの更新作業は、Shiftのサービスとその後の手動確認と編集のハイブリッドになりました。Shiftで変更の対象を学び更新を理解しそれを適用という感じです。もちろんShiftの作業は後者の手動の作業に比べて非常に安い(29ドル)のですが、一度理解できたら、他のプロジェクトでの同様な更新にShiftの利用は必要ないかもしれません。多分に将来はLaravelの更新作業は、AIですべて完璧に行ってくれるかもしれないですね。現在はまさに過渡期です。

メルマガ購読の申し込みはこちらから。

By khino