Laravel 13では、多くのモデルを占拠していた $table$fillable$casts プロパティを、ネイティブなPHP属性(Attributes)に置き換えることができるようになりました。この変更は、モデルの設定からイベントリスナー、Mailablesに至るまで、12以上のフレームワーク機能に適用され、既存のコードを壊すことなく動作します。

Laravelがネイティブ属性を追加した理由

Laravelは長らく「マジックストリング」に依存してきました。これは、モデルクラスの冒頭に配置されるカラム名や非表示フィールドの配列のことです。これらの配列は、IDEに対して基盤となるスキーマに関するヒントを与えないため、カラム名のリファクタリングが気づかぬうちに漏れてしまうことがあります。設定を実際の型付けされたコードに移行することで、Laravelは開発者がクラス本体をビジネスロジックに集中させつつ、エディタによるオートコンプリート、型チェック、名前変更リファクタリングツールを活用できるようにします。

フレームワークはPHPのリフレクションAPIを介して属性を読み取り、その結果をキャッシュするため、実行時のオーバーヘッドは事実上ゼロです。既存のプロパティベースのモデルは現在と同様に動作し続けるため、新しい構文を段階的に導入できます。

得られるメリット

  • 型付けされた設定 – 属性は型付きの引数を受け入れるため、マジックストリングを排除できます。カラム名を変更すると、IDEが更新が必要なすべての箇所を指摘してくれます。
  • よりクリーンなクラス本体 – すべての設定はクラス名の上に配置され、クラス本体にはリレーション、スコープ、メソッドのみが含まれるようになります。
  • 優れたIDE体験 – 文字列の配列では不可能な、属性の引数に対するオートコンプリートや静的解析が可能になります。
  • 破壊的変更なし – Laravelは古いプロパティと新しい属性の両方を読み取るため、混在したコードベースでも問題なく動作します。

ステップバイステップ移行ガイド

  1. 移行するモデルを特定する
    モデルファイルを開きます。最初の数十行が $table$fillable$hidden、または casts() メソッドで占められている場合は、移行の候補です。

  2. 属性クラスを追加する
    ファイルの冒頭で、置き換えるプロパティに対応する属性クラスをインポートします(例:TableFillableCasts)。これらの属性はLaravelに標準で含まれています。

  3. プロパティ宣言を属性に置き換える

    // Before
    protected $table = 'site_deployments';
    protected $fillable = ['site_id', 'server_id', 'status'];
    protected function casts(): array
    {
        return ['is_rollback' => 'boolean'];
    }
    
    // After
    #[Table('site_deployments')]
    #[Fillable(['site_id', 'server_id', 'status'])]
    #[Casts(['is_rollback' => 'boolean'])]
    class Deployment extends Model
    {
        // business logic only
    }
    

    属性の構文はクラス宣言の直上に記述します。属性が機能することを確認した後、元のプロパティやメソッドを削除してください。

  4. テストスイートを実行する
    一括代入(mass-assignment)、シリアライズ、およびカスタムキャストが以前と同様に動作することを確認します。Laravelの属性処理はキャッシュされるため、テストが失敗する場合は、通常、属性の引数のタイポ(打ち間違い)が原因です。

  5. 小規模なバッチでコミットしてデプロイする
    移行したモデルをフィーチャーブランチにプッシュし、CIパイプラインを通過した後にマージして、一部のサーバーに展開します。古いプロパティ構文も引き続きサポートされているため、不適切な参照があっても実行時エラーにはなりません。

  6. 名前空間ごとに繰り返す
    コードベース全体を一度に書き換えるのではなく、論理的なモデルのグループ(例:すべての請求関連エンティティ)ごとに属性へ移行し、次のグループへと繰り返します。これにより、リグレッション(退行)の影響範囲を最小限に抑えることができます。

ツールとセーフティネット

  • Rector – 反復的なプロパティ構文を属性に変換できる自動リファクタリングツールです。コードベースのコピーに対して実行し、差分を確認して、正しいと思われる変更を適用します。
  • 自動テスト – Laravel組み込みのテストユーティリティが、一括代入やJSON出力の不一致を検知します。移行の各ステップの後に、テストがパスしていることを確認してください。
  • フィーチャーフラグ – 素早くロールバックする必要がある場合は、新しい属性の使用を、古い設定と新しい設定を切り替えるフラグでラップします。

移行をスキップしてもよい場合

プロジェクトが小さく、安定しており、めったに変更されない場合は、モデルをクリーンにするメリットが変換の労力に見合わないかもしれません。属性構文はオプションです。従来のプロパティによるアプローチを無期限に使用し続けることができます。逆に、活発に開発されているアプリケーション、特にモデルが大規模であったりスキーマ変更が頻繁であったりする場合は、早い段階で属性を採用することで将来的な摩擦を軽減できます。

次に注目すべき点

Laravel 13の属性サポートは、モデルだけでなく、イベントリスナー、通知(Notifications)、Mailables、ブロードキャストイベントにも広がっています。コミュニティがこれらの領域で構文を採用するにつれ、同様のリファクタリングパターンが登場するでしょう。今後のマイナーリリースで導入される新しい属性クラスについては、公式のアップグレードガイドを注視しておいてください。

要点: Laravel 13は、よりスリムでIDEフレンドリーなモデルへと、コストをかけずに移行できる道筋を提供します。一度に一つの名前空間ずつ変換を進め、Rectorとテストスイートを活用することで、設定ファイルのダンプのようなクラスではなく、ビジネス仕様書のように読みやすいクラスへと進化させることができるでしょう。