Laravel 9 Upgrade Memo
Laravel9が2022/02/08リリースされたので、新機能およびアップグレードメモ。Deepl だったり意訳だったりするので、本家本元を読んでくださいな。
~~ 前回の LTS が Laravel 6(2019/09/03 Release)なので、それから久しぶりの LTSです。~~
-
2022/02/10 15:13:00 : LTS 外れてた。理由わからんけど Symfony6 の PHP Minimum Version が 8.1+ になりそうだからっぽい?これ、ふわふわしそう。
-
https://github.com/laravel/docs/commit/1249422c2ea59f9bc8eac468b0ffe108658214fe
-
2022/03/29:: Rendering Inline Blade Templates に追記
サポートしているPHPが 8.0〜8.1(現在の所。おそらく8系はサポート?)となっており、7.x 系は動きません。これにともない named arguments -- www.php.net がサポートされます。
バグフィックスは 2024/02/08まで、セキュリティフィックスは 2025/02/08 までです。
わりとクソデカ変更ですので、アップグレードは注意です。 PHP7→PHP8 で返り値が追加とか、SymfonyMail へ変更とか、 FlySystem3.x へ対応とか。
- see : Release Note : Laravel.com
- see : Upgrade Note : Laravel.com
- Update : 2024-02-19 : TrustedProxy の項目を更新
変更点
多いので、右側の一覧を見てください。
変更量が特に大きいもの
- PHP8.0 以上が必須、PHP8.1以上が推奨、になりました。PHP8.1以上が推奨なのは Enum を使えたほうが良いからです。
- SwiftMailer の使用が終わり、SymfonyMail へ変更されました。それの対応する変更が大幅にあります。
- AWS S3 等にファイルを置く FlySystem の利用バージョンが 3.0 系に更新されました。これに対応する変更があります。
アップグレード方法
composer.json を変更してください。
- 変更:
laravel/framework:^9.0
- 変更:
nunomaduro/collision:^6.0
- 追加:
facade/ignition
- 追加:
spatie/laravel-ignition": "^1.0"
さらに Notification のアップグレードもありますので、各自頑張ってください。
[NEW][インパクト高] PHP8.0
PHP 8.0.2 以上が推奨です。ただ、Enum使うために PHP8.1以上が良いかも。
see : https://laravel.com/docs/9.x/upgrade#updating-dependencies
Return Type
PHP Methods の offsetGet
,offsetSet
の返り値が付きました。ゴリゴリ書いて行きましょう。
Application
[変更][インパクト低] The Application Contract
Illuminate\Contracts\Foundation\Application
クラスの storagePath
に $path
引数が付きました。継承して使っている時は public function storagePath($path = '');
的にしましょう。
[変更][インパクト低] Exception Handler ignore Method
同じクラスの ignore
メソッドが public
になりましたので、追従変更をしてください。
Blade
[追加] Rendering Inline Blade Templates
see : https://laravel.com/docs/9.x/releases#rendering-inline-blade-templates
テンプレートファイルがなくても Blade のテンプレートを指定して実行することが出来ます。
use Illuminate\Support\Facades\Blade;
return Blade::render('Hello, {{ $name }}', ['name' => 'Julian Bashir']);
追記:: 2022/03/29 :: 調べたら v8.80 から使える機能みたいです。なんちゅうバージョン番号だ… see: https://github.com/laravel/framework/commit/5e104a0244f82d2f7c562044fc8208ace49cb633
[追加] Slot Name Shortcut
x-slot
タグに <x-slot name="title">
としてたところを <x-slot:title>
という感じでショートカットができるようになりました。
[追加] Checked / Selected Blade Directives
@checked
および @selected
タグが追加されました。(三項演算子でええやんけ)
<input type="checkbox"
name="active"
value="active"
@checked(old('active', $user->active)) />
<select name="version">
@foreach ($product->versions as $version)
<option value="{{ $version }}" @selected(old('version') == $version)>
{{ $version }}
</option>
@endforeach
</select>
[追加] Bootstrap 5 Pagination Views
BootStrap5 を使うようになりましたので、使う時は下記のような感じで App\Providers\AppServiceProvider
に書き込んでください。
use Illuminate\Pagination\Paginator;
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Paginator::useBootstrapFive();
}
[変更][インパクト低] Lazy Collections & The $loop Variable
ループをしているとき、$loop
を使っている場合は Lazy Collections 全体がメモリーにロードされるので、Lazy Collectionsの使用が無意味になります。
Collections
[変更][インパクト低] The Enumerable Contract
-
Illuminate\Support\Enumerable
クラスにsolo
メソッドが追加されました。使用している時は、このメソッドを実装してください。 -
reduceWithKeys
メソッドはreduce
メソッドと同意なので、廃止されました。 -
reduceMany
メソッドはreduceSpread
に名称が変わりました。
Container
[変更][影響ほぼない] The Container Contract
Illuminate\Contracts\Container\Container
にある scoped
と scopedIf
が新しく実装されました。継承して実装をしている場合は実装をしてください。
[変更][影響ほぼない]The ContextualBindingBuilder Contract
Illuminate\Contracts\Container\ContextualBindingBuilder
に giveConfig
が新しく実装されました。使用している時は新しく実装してください。
Database
[追加] Full Text
see : https://laravel.com/docs/9.x/releases#full-text
MySQL/PostgreSQL でフルテキスト検索のインデックスを作成するオプションが付きました。
$table->text('bio')->fullText();
使う時はこんな感じ。
$users = DB::table('users')
->whereFullText('bio', 'web developer')
->get();
[追加] Laravel Scout Database Engine
よくわかんないけど、 Scout エンジンを Eloquent から使えるようになるっぽい。
see : https://laravel.com/docs/9.x/scout
[変更][インパクト並] Postgres "Schema" Configuration
PostgreSQLを使う場合の config/database.php
にある、接続パスを設定するために使用するスキーマ設定オプションは search_path
に名前を変更する必要がある。
[変更][インパクト低] Schema Builder registerCustomDoctrineType Method
Illuminate\Database\Schema\Builder
の registerCustomDoctrineType
メソッドが廃止されました。代わりに registerDoctrineType
メソッドを使うか、 config/database.php
にカスタムの Doctrine タイプを書いてください。
Eloquent
[追加] Improved Eloquent Accessors / Mutators
今まで Mutators として getHogeAttribute/setHogeAttribute
となっていましたが、もっと楽になります。
use Illuminate\Database\Eloquent\Casts\Attribute;
public function name(): Attribute
{
return new Attribute(
get: fn ($value) => strtoupper($value),
set: fn ($value) => $value,
);
}
さらに Illuminate\Database\Eloquent\Casts\Attribute
を継承してカスタマイズをすることが出来ます。
use App\Support\Address;
use Illuminate\Database\Eloquent\Casts\Attribute;
public function address(): Attribute
{
return new Attribute(
get: fn ($value, $attributes) => new Address(
$attributes['address_line_one'],
$attributes['address_line_two'],
),
set: fn (Address $value) => [
'address_line_one' => $value->lineOne,
'address_line_two' => $value->lineTwo,
],
);
}
[追加] Enum Eloquent Attribute Casting
Enumを使って cast をすることができます。PHP8.1+のみ。
use App\Enums\ServerStatus;
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'status' => ServerStatus::class,
];
enum Cast を使えば下記のように書くことが出来ます。
if ($server->status == ServerStatus::provisioned) {
$server->status = ServerStatus::ready;
$server->save();
}
[変更][インパクト並] Custom Casts & null
DEEPL: Laravelの以前のリリースでは、カスタムキャストクラスのsetメソッドは、キャスト属性がNULLに設定されている場合は呼び出されませんでした。しかし、この動作はLaravelのドキュメントと矛盾していました。Laravel 9.xでは、キャストクラスのsetメソッドは、提供された$value引数としてnullで呼び出されます。したがって、カスタムキャストがこのシナリオを十分に処理できるようにする必要があります。
/**
* Prepare the given value for storage.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param AddressModel $value
* @param array $attributes
* @return array
*/
public function set($model, $key, $value, $attributes)
{
if (! $value instanceof AddressModel) {
throw new InvalidArgumentException('The given value is not an Address instance.');
}
return [
'address_line_one' => $value->lineOne,
'address_line_two' => $value->lineTwo,
];
}
[変更][インパクト並] Belongs To Many firstOrNew, firstOrCreate, and updateOrCreate Methods
よくわかんない。多対多関連でつかう中間テーブルの扱いに対して変更があるみたい?
[変更][インパクト低] The touch Method
touch
メソッドに引数 $attribute
が付きましたので、追従変更をしてください。
Encryption
[変更][インパクト低] The Encrypter Contract
Illuminate\Contracts\Encryption\Encrypter
クラスに getKey
メソッドが実装されましたので、実装をしている場合は追従変更をしてください。
Facades
[変更][インパクト低] The getFacadeAccessor Method
getFacadeAccessor
メソッドの返り値がは常にコンテナーの Binding Key を返すようにしてください。以前のリリースまではオブジェクトを返すようにしていましたが、近いうちに廃止されますので、クラスを返すようにしてください。
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return Example::class;
}
FlySystem
FlySystem を 3.x 系にアップグレードしました。
see : https://laravel.com/docs/9.x/upgrade#flysystem-3
[Upgrade][インパクト高] ドライバーアップデート
S3 などのパッケージをアップデートしてください。
> composer require --with-all-dependencies league/flysystem-aws-s3-v3 "^3.0"
[変更][インパクト高] put, write, writeStream の挙動変更
put, write, writeStream
のメソッドの挙動が変わります。これからは既存ファイルに対して上書きを実行します。ファイルの存在確認は書き出す前に実効をしてください。
[変更][インパクト高] Reading Missing Files
存在しないファイルにアクセスした時に null
を返していましたが Illuminate\Contracts\Filesystem\FileNotFoundException
の例外を投げるようになりました。
[変更][インパクト高] Deleting Missing Files
存在しないファイルを削除した時は true
を返すようになります。
[変更][インパクト高] Cached Adapters
FlySystem から cached adapters
のサポートがなくなりました。それにともない Laravel もサポートしなくなります。
[変更][インパクト高] Custom Filesystems
カスタマイズしている時に変更が必要みたい。
// Laravel ~8
use Illuminate\Support\Facades\Storage;
use League\Flysystem\Filesystem;
use Spatie\Dropbox\Client as DropboxClient;
use Spatie\FlysystemDropbox\DropboxAdapter;
Storage::extend('dropbox', function ($app, $config) {
$client = new DropboxClient(
$config['authorization_token']
);
return new Filesystem(new DropboxAdapter($client));
});
// Laravel 9~
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Support\Facades\Storage;
use League\Flysystem\Filesystem;
use Spatie\Dropbox\Client as DropboxClient;
use Spatie\FlysystemDropbox\DropboxAdapter;
Storage::extend('dropbox', function ($app, $config) {
$adapter = new DropboxAdapter(new DropboxClient(
$config['authorization_token']
););
return new FilesystemAdapter(
new Filesystem($adapter, $config),
$adapter,
$config
);
});
[変更][インパクト低] The FILESYSTEM_DRIVER Environment Variable
.env
にある変数 FILESYSTEM_DRIVER
が FILESYSTEM_DISK
に変更されました。
もし変更したい時は変更をしてください。変更をしなくても現状は問題ないはず。
[変更][インパクト低] The "Cloud" Disk
2020/11 のリリースより cloud
Disk Configuration は削除されました。
HTTP Client
[変更][インパクト中] Default Timeout
Laravel の HTTP_Client にある default timeout が 30 秒になりました。変更をする場合は下記のようにすればいいと思います。
$response = Http::timeout(120)->get(...);
[変更][インパクト低] HTTP Fake & Middleware
Http::fake()
としても GuzzleMiddleware は実行されませんでしたが、これからは動くようになります。
[変更][インパクト低] HTTP Fake & Dependency Injection
力尽きた
Mailer
大幅にテコ入れです。
[NEW][インパクト高] Symfony Mailer
SwiftMailerが使われていましたが、2021/12からメンテナンスがされていないので、SymfonyMailerに乗り換えました。
これにともない、たくさんの変更点があります。(白目)
see : Upgrade : Symfony Mailer -- laravel.com
ドライバーとしての前提条件
mailgun や postmark のドライバーをそれぞれインストールする必要があります。
> composer require symfony/mailgun-mailer
> composer require symfony/sendgrid
send/html/text/plain の返り値の変更
今まで送信数を返していたのが Illuminate\Mail\SentMessage
インスタンスに変更されました。このオブジェクトは Symfony\Component\Mailer\SentMessage
の継承クラスで getSymfonySentMessage
で動的に作成されたメッセージのアクセスができます。
Swift
to Symfony
Rename Laravel 8 の頃と 9 になってからでは、メソッド名が変更されています。
// Laravel 8.x...
$this->withSwiftMessage(function ($message) {
$message->getHeaders()->addTextHeader(
'Custom-Header', 'Header Value'
);
});
// Laravel 9.x...
use Symfony\Component\Mime\Email;
$this->withSymfonyMessage(function (Email $message) {
$message->getHeaders()->addTextHeader(
'Custom-Header', 'Header Value'
);
});
Email
クラスのメソッドは Symfony Mailer -- symfony.com で確認できます。
Illuminate\Mail\Message
methods
Proxied Illuminate\Mail\Message
は存在しないメソッドにアクセスした場合は Swift_Message
のメソッドを呼び出していました。したがって、対応するメソッドを Symfony\Component\Mime\Email
に変更する必要あります。
// Laravel 8.x...
$message
->setFrom('taylor@laravel.com')
->setTo('example@example.org')
->setSubject('Order Shipped')
->setBody('<h1>HTML</h1>', 'text/html')
->addPart('Plain Text', 'text/plain');
// Laravel 9.x...
$message
->from('taylor@laravel.com')
->to('example@example.org')
->subject('Order Shipped')
->html('<h1>HTML</h1>')
->text('Plain Text');
Generated Messages IDs
よくわからん
Forced Reconnections
よくわからん。
メール送信時の接続に失敗した時に再接続をするが、それも失敗した時は例外を投げて終わる感じ?
SMTP Stream Options
SMTP の stream オプションがサポートされなくなりました。代わりに直接に定義をすることになります。これらのメールの設定は Symfony の Transport Setupを参考にしてください。
'smtp' => [
// Laravel 8.x...
'stream' => [
'ssl' => [
'verify_peer' => false,
],
],
// Laravel 9.x...
'verify_peer' => false,
],
auth_mode
SMTP mail 設定の auth_mode
はサポートされなくなりました。
Failed Recipients
メールの送信後に失敗した受信者リストを取得することができなくなりました(え、できたの?)
代わりに送信に失敗すると Symfony\Component\Mailer\Exception\TransportExceptionInterface
の例外を放つようになりました。メールアドレスの検証は送信前にチェックするようにしましょう。
Packages
[変更][インパクト中] The lang Directory
resources/lang
ディレクトリパスが app()->langPath()
でアクセスできるようになります。
queue
[変更][インパクト中] The opis/closure Library
opis/closure
を使わず laravel/serializable-closure
に変更されます。これにともない Illuminate\Queue\SerializableClosureFactory
と Illuminate\Queue\SerializableClosure
は削除されました。
もし使用し続ける場合は https://github.com/laravel/serializable-closure を個別でインポートしてください。
[変更][インパクト中] The Failed Job Provider flush Method
flush
メソッドの実装は Illuminate\Queue\Failed\FailedJobProviderInterface
にありますが、$hour
引数が追加されました。それは、どれだけ古い失敗したJobかを図る(単位は時間)のに使うみたいです?
Session
[変更][インパクト低] The getSession Method
力尽きた。
Routing
Routing に色々と機能が増えました。
[NEW] Implicit Route Bindings With Enums
see : https://laravel.com/docs/9.x/releases#implicit-route-bindings-with-enums
PHP8.1+ から Enum が実装されました。それに合わせて、Laravel9 も Routing に Enum を使えるようになりました。
enum Category: string
{
case Fruits = 'fruits';
case People = 'people';
}
Route::get('/categories/{category}', function (Category $category) {
return $category->value;
});
[NEW] Forced Scoping Of Route Bindings
see : https://laravel.com/docs/9.x/releases#forced-scoping-of-route-bindings
よくわかんない
[NEW] Controller Route Groups
Controller の指定を controller
メソッドで使用できるようになりました。
Route::controller(\App\Http\Controllers\OrderController::class)->group(function () {
Route::get('/orders/{id}', 'show');
Route::post('/orders', 'store');
});
[NEW] Improved route:list CLI Output
route:list
の出力が人道的になりました。
Exception Page
何か開発中に出る例外エラーの画面がリッチになったっぽい。
Test
[NEW] Test Coverage Using Artisan test Command
Coverage の出力がわかりやすくなりました。そして --min
をつけると、Coverage の敷居として設定して、Coverage の結果が min
で指定した値より低い時はエラーを起こすようになります。
[変更][インパクト中] The assertDeleted Method
全ての assertDeleted
は assertModelMissing
が呼ばれます。
[変更][インパクト低] Trusted Proxies
追記 必要なコマンドが抜けていたので修正。
app/Http/Middleware/TrustProxies.php
がある時、このファイルを編集します。
-
そのファイルの
use Fideloper\Proxy\TrustProxies as Middleware
をuse Illuminate\Http\Middleware\TrustProxies as Middleware
に変更する -
そのファイルにある
TrustProxies
クラスのクラス変数$headers
を下記に編集します。protected $headers = Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_AWS_ELB;
-
composer remove fideloper/proxy
を実行して削除します。
see: https://github.com/fideloper/TrustedProxy
Validator
[追加] Improved Validation Of Nested Array Data
配列で来たデータに対して、個々の要素チェックができるようになります…?
use App\Rules\HasPermission;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
$validator = Validator::make($request->all(), [
'companies.*.id' => Rule::forEach(function ($value, $attribute) {
return [
Rule::exists(Company::class, 'id'),
new HasPermission('manage-company', $value),
];
}),
]);
[変更][インパクト中] Form Request validated Method
validated
メソッドの引数が変更されたみたいです。
[変更][インパクト中] The password Rule
現在登録しているパスワードと認証をするのに current_password
メソッドに変更されました。
[変更][インパクト中] Unvalidated Array Keys
よくわかんない
IDE Support
[NEW] Improved Collections IDE Support
IDE-Helper とどう違うのかわからないけど、公式としてIDE/PHPStanをサポートします。
Helper
str
str
の返り値が Illuminate\Support\Stringable
を返すようになりました。
to_route
to_route
でいろいろ……?
[変更][インパクト中] The when / unless Methods
when/unless
メソッドに変更があったみたい。使ったことがないからわからない…
Discussion
langディレクトリのとこは、resources以下からデフォルトでプロジェクトルートに移動したよ、ってことみたいですね。
resources以下のままでもちゃんと認識してくれるけど、パッケージ作者でlangファイルを扱う場合はパスを表すのに
app()->langPath()
使ってね、って感じかと