1年半振りのメジャーバージョンアップ(予定)！Laravel9の新機能ピックアップ！

[Laravel Advent Calendar 2021](https://qiita.com/advent-calendar/2021/laravel) 1日目の投稿です。
来月(2022年1月)、1年半ぶりのLaravelのメジャーバージョンアップするのでLaravel9の主要な変更点をまとめてみました。

## リリース日

- Laravel 8: 2020年9月
- Laravel 9: 2022年1月(予定)
- Laravel 10: 2023年1月(予定)
- Laravel 11: 2024年1月(予定)

[Symfony6.0](https://github.com/symfony/symfony/releases/tag/v6.0.0)が2021年11月30日にリリースされました。それに伴ってLaravel 9のリリースが2022年1月に延期されています。
また、Laravel 9以降は半年周期のメジャーリリースが1年周期になっています。

|Version|PHP (*)|Release|Bug Fixes Until|Security Fixes Until|
|:----|:----|:----|:----|:----|
|6 (LTS)|7.2 - 8.0|September 3rd, 2019|January 25th, 2022|September 6th, 2022|
|7|7.2 - 8.0|March 3rd, 2020|October 6th, 2020|March 3rd, 2021|
|8|7.3 - 8.1|September 8th, 2020|July 26th, 2022|January 24th, 2023|
|9 (LTS)|8.0 - 8.1|January 25th, 2022|January 30th, 2024|January 28th, 2025|
|10|8.0 - 8.1|January 24th, 2023|July 30th, 2024|January 28th, 2025|

https://laravel.com/docs/8.x/releases

## インストール要件

最低でも PHP8.0 以上である必要があります。
Laravel 9の内部でSymfony6.0が利用されており、PHP8.0が最小要件があるためLaravel 9にも同じ制限が適用されます。

## 新機能ピックアップ

### Anonymous Stub Migrations

[Laravel v8.37.0](https://github.com/laravel/framework/releases/tag/v8.37.0) でクラス名の衝突を防ぐために匿名マイグレーション機能がリリースされました。
Laravel 9.xでは `php artisan make:migration` 実行時に生成されるファイルが匿名マイグレーションがデフォルトとなります。(Laravel8.xではデフォルトのマイグレーションテンプレートはクラス名付きで生成されますが、匿名マイグレーションは利用可能です。)

```php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
 
return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('people', function (Blueprint $table) {
            $table->string('first_name')->nullable();
        });
    }
};
```

これにより名前被りを気にせずマイグレーションファイルを作成できます。
マイグレーションファイル名は日付プレフィックスが付くので同名ファイルでも問題ありません。
また、稀によく発生していたマイグレーションクラスをリネームしてオートローダーが壊れる問題もこれで解消されそうです。

https://github.com/laravel/framework/pull/36906

### 新しくクエリビルダーインターフェイスが追加

- [`Illuminate\Database\Eloquent\Relations`](https://github.com/laravel/framework/blob/master/src/Illuminate/Contracts/Database/Eloquent/Relations)
- [`Illuminate\Database\Eloquent\Builder`](https://github.com/laravel/framework/blob/master/src/Illuminate/Database/Eloquent/Builder.php)
- [`Illuminate\Database\Query\Builder`](https://github.com/laravel/framework/blob/master/src/Illuminate/Database/Query/Builder.php)

これらのクエリビルダークラス群が1つのインターフェース [`Illuminate\Contracts\Database\Query\Builder`](https://github.com/laravel/framework/blob/master/src/Illuminate/Contracts/Database/Query/Builder.php) と契約しました。

https://github.com/laravel/framework/pull/37956

### 文字列関数の内部実装の変更

https://github.com/laravel/framework/pull/38011

最小要件がPHP8.0ということで、下記の関数の内部実装が変更されています。

```
Str::contains();
Str::startsWith();
Str::endsWith();
```

`str_contains()`、`str_starts_with()` および `str_ends_with()` 関数が利用されています。
現時点では特に非推奨となっていませんが、PHPの標準関数で実現できるので今後はもしかしたら非推奨になる関数かもしれませんね。

### SwiftMailerからSymfonyMailerへ

https://github.com/laravel/framework/pull/38481

SwiftMailerが非推奨となり、Laravel9ではSymfonyMailerを使用するように変更されています。

### lang ディレクトリがトップレベルへ

https://twitter.com/taylorotwell/status/1444331118615011331

Laravel8までは `resources/lang` でしたがLaravel9からトップレベルへ移動されました。

### Flysystem v2

AWS S3をLaravelで操作したい時に使うライブラリ[thephpleague/flysystem-aws-s3-v3](https://github.com/thephpleague/flysystem-aws-s3-v3)

v2系はLaravel8で動作しませんでしたが、Laravel9からv2系がサポートされます。
アップグレードの際はご注意ください。

https://github.com/laravel/framework/pull/33612
https://qiita.com/ucan-lab/items/61903ce10a186e78f15f

## Laravel インストーラにAPIオプションの追加

https://twitter.com/taylorotwell/status/1457829364163387392?s=20

```
$ laravel new foo --api
```

HTMLを返さないAPIシステムのためのapiオプションがLaravelインストーラに追加されるそうです。
css, js関連ファイルが削除されたLaravelプロジェクトテンプレートを構築します。
(管理画面はやっぱり簡単なHTMLを返したいとかありそう...笑 簡単に戻せるならアリかな？)

### server.php がLaravelのプロジェクトルートから削除

https://twitter.com/enunomaduro/status/1470755959479939084?s=20

`server.php` は `php artisan server` のコマンドを実行する際に使用されるファイルです。

`laravel/laravel` のルートディレクトリ配下にあった server.php が `laravel/framework` のフレームワーク本体の `src/Illuminate/Foundation/resources/server.php` に移動になりました。
Laravel9へアップグレードした際は不要なファイルになるのでこのファイルを削除する必要がありそうです。

- https://github.com/laravel/laravel/pull/5747
- https://github.com/laravel/framework/pull/40034

## Laravel8で追加された新機能

Laravel8.xで新しく追加された機能で気になったものをご紹介します。

### Eloquent N+1検知機能

https://twitter.com/taylorotwell/status/1395087054254526474

Laravel v8.43.0 でN+1検知機能がしれっと追加されていました。
N+1クエリーがあると例外が発生するため開発プロセスの初期段階でN+1クエリーを発見できます。

https://laravel-news.com/disable-eloquent-lazy-loading-during-development
https://github.com/laravel/framework/pull/37363
https://github.com/laravel/framework/releases/tag/v8.43.0

### Enum型のサポート

https://twitter.com/taylorotwell/status/1460630566240456713?s=20

Laravel v8.71.0 でEnum型を便利に扱えるようにキャスト機能やクエリー周りのサポートが行われています。

https://github.com/laravel/framework/pull/39608
https://github.com/laravel/framework/pull/39492
https://github.com/laravel/framework/pull/39597
https://github.com/laravel/framework/releases/tag/v8.71.0
https://github.com/laravel/framework/releases/tag/v8.70.0

## 参考

- https://laravel-news.com/laravel-9
- https://blog.laravel.com/laravel-9-release-date