開発中のLaravel 11をチラ見 〜 Eloquent Modelのキャストがcasts()でも定義可能に
こんにちは、ナカエです。 猛暑日の連続記録に挑戦している京都からお届けします。
本日の記事は、Laravel11でのEloquent Modelのキャスト機能の変更予定について調査した内容です。
※ 本記事で扱うのはリリース前の開発中の情報であり、リリース時には変更となる可能性があるのでお気をつけください。
環境
- Mac OS 13.4.1(Ventura)
- PHP 8.2.6
- Composer 2.5.8
- Laravel 11系開発中のmasterブランチ (commit: e96d21dd2d655ed623ab7b0b4e07f9e9ee3418fd)
Laravel 11ので予定されている新機能の一つ
気になる情報を見かけたのは Laravel News の Laravel 11の記事 でした。 Laravel 11で予定されている新機能を紹介する記事です。
その中にModel casts changesという項目があり、こちらはEloquent Modelにおいてcasts()メソッドを通じたキャストの設定が可能になるというもの。
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
'options'=› AsEnumCollection::of(UserOption::class),
];
}
※ 上記Laravel Newsの記事より引用
メソッドの返り値でキャストが設定できると何が嬉しいか
$castsプロパティ単体で定義する場合と比較すると、プロパティの初期値の定義には使えない関数の呼び出しやクラスのインスタンス化が楽に行えるようになり設定の柔軟性が上がります。
例えば従来の $castsプロパティによる設定では、AsEnumCollection(Enumのコレクションにキャストする)などが涙ぐましい文字列連結にて表現されていました。
protected $casts = [
'statuses' => AsEnumCollection::class.':'.ServerStatus::class,
];
※ ドキュメントの Eloquent: Mutators & Casting より引用
これがcasts()メソッドによる設定ではより素直に表現できていることがわかります。
$castsプロパティとcasts()メソッドの関係について
個人的に
- $castsプロパティの値とcasts()メソッドの返り値の優先順位
- 今後$castsプロパティがdeprecatedになる可能性
などが気になったので、開発中のソースコードを確認することにしました。
Composerでバージョンにdev-masterを指定したLaravelプロジェクトを作成し、Eloquent ModelのConcern(Trait)の1つであるHasAttributes
の実装を見てみます。
protected function initializeHasAttributes()
{
$this->casts = $this->ensureCastsAreStringValues(
array_merge($this->casts, $this->casts()),
);
}
Eloquent ModelのコンストラクタでModel::initializeTraits()からこちらのメソッドが呼ばれるようになっているため、Eloquent Modelをインスタンス化した時点で$castsプロパティにcasts()メソッドの返り値がマージ済みということになります。
Laravel11でも$castsプロパティが主体であり、casts()メソッドはプラスアルファとの認識でも良さそうです。HasAttributesトレイトにはmergeCasts()メソッドなども存在するため、互換性のためにはインスタンスの状態たるプロパティを軸にするのは妥当でしょう。
同時に$castsプロパティとcasts()メソッドで同じキーに対するキャストを定義した場合は、casts()メソッドでの定義で上書きされる点には注意が必要そうです。
まとめ
Laravel11でのEloquent Modelのキャスト機能の変更予定について調査しました。
Laravel 11系へのアップグレード時に $castsプロパティ を casts()メソッドに移し替えるというようなことは不要そうでホッとしました。
ただ、新規実装時に$castsプロパティとcasts()のどちらを優先して使うかについては、コーディング規約で縛ったほうが良さそうですね。
最後にもう一度念押しですが、本記事が参考にしているのは開発中のLaravelのソースコードであり、リリース時には変更されている可能性があることにご注意ください。
来年の第一四半期に予定されているLaravel11のリリースを楽しみに待ちましょう。