【Laravel】Laravel13のPHP Attributes化とQueue Routing・JSON:API・Cache::touch()(実務Tips集)

laravelアイキャッチ Laravel

こんにちは、かつコーチです。

2026年3月にリリースされたLaravel13、もう触ってみましたか。

AI SDKやセマンティック検索のような派手な新機能に注目が集まりがちですが、実は日々の実装を地味に楽にしてくれる変更も多く入っています。

今回は、実務で「これ地味に便利」と感じたLaravel13の4つの機能を、Before/Afterで比較しながら紹介します。

  • PHP Attributes:モデルやジョブの設定をコードの意図が分かりやすい形で書ける
  • Queue Routing:ジョブごとの接続先・キュー名を一元管理できる
  • JSON:API Resources:APIレスポンスをJSON:API標準仕様に沿わせられる
  • Cache::touch():キャッシュのTTLだけを延長できる

どれもLaravel12までの書き方がそのまま動くので、慌てて全部書き換える必要はありません。

「知っておくと選択肢が増える」くらいの気持ちで読んでみてください。

PHP Attributesでモデル・ジョブの設定を書く

従来のプロパティ宣言との違い

Laravel13では、モデルやジョブの設定をPHP Attributes#[...]の形で書く、PHP8系の言語機能)で表現できるようになりました。

PHP Attributesとは、クラスやプロパティに「メタ情報(付加的な設定情報)」を付与するための構文です。

以前からLaravelでも一部使われていましたが、Laravel13ではモデルの$fillableやジョブのミドルウェア設定、リトライ回数といった項目まで対応範囲が広がっています。

// ❌ Before:プロパティ宣言で設定を書く(Laravel12までのやり方)
class Article extends Model
{
    protected $fillable = ['title', 'body', 'status'];
}
// ✅ After:PHP Attributesで設定を書く(Laravel13の書き方)
use Illuminate\Database\Eloquent\Attributes\Fillable;

#[Fillable(['title', 'body', 'status'])]
class Article extends Model
{
    //
}

見ての通り、プロパティ宣言方式は引き続き動作します。

つまりLaravel13にアップグレードしても、既存コードを書き換える義務はありません。

ジョブのミドルウェア・リトライ回数も宣言的に書ける

Queueジョブのミドルウェアやリトライ回数も、Attributesでクラス定義の直下にまとめて書けるようになりました。

// ❌ Before:メソッドの中で個別に定義する
class SendInvoiceEmail implements ShouldQueue
{
    public $tries = 3;

    public function middleware()
    {
        return [new WithoutOverlapping('invoice')];
    }
}
// ✅ After:Attributesでクラス定義の直下にまとめる
use Illuminate\Queue\Attributes\Tries;
use Illuminate\Queue\Attributes\Middleware;

#[Tries(3)]
#[Middleware('auth')]
class SendInvoiceEmail implements ShouldQueue
{
    //
}

筆者が実際に触ってみて感じたのは、クラスを開いた瞬間に「このジョブは3回までリトライする」「authミドルウェアがかかっている」と一目で分かる点です。

メソッドの中身まで読まないと設定が分からなかった従来の書き方に比べて、コードレビュー時の見通しが良くなりました。

Queue Routingでジョブの接続先を一元管理する

Queue::route()の基本

Laravel13で追加されたQueue Routingは、Queue::route()を使ってジョブごとの接続(connection)とキュー名(queue)を一元管理できる仕組みです。

これまでは、ジョブクラスの中に$connection$queueプロパティを個別に書くのが一般的でした。

// ❌ Before:ジョブごとに接続先をハードコードする
class ProcessPodcast implements ShouldQueue
{
    public $connection = 'redis';
    public $queue = 'podcasts';
}

class SendWelcomeEmail implements ShouldQueue
{
    public $connection = 'redis';
    public $queue = 'emails';
}
// ✅ After:AppServiceProviderなどで一元管理する
use Illuminate\Support\Facades\Queue;

public function boot(): void
{
    Queue::route(ProcessPodcast::class, connection: 'redis', queue: 'podcasts');
    Queue::route(SendWelcomeEmail::class, connection: 'redis', queue: 'emails');
}

なぜ一元管理がうれしいのか

ジョブの数が増えてくると、「このジョブはどのキューに流れているんだっけ?」と探すのに時間がかかることがあります。

Queue::route()で1箇所にまとめておけば、キュー構成を変更したいときもここだけ見れば把握できます。

インフラ側でキュー名の運用ルールを変えた際、対象ジョブのクラスファイルを1つずつ開いて修正する必要がなくなるのは、地味に大きなメリットです。

JSON:API Resourcesで標準仕様のレスポンスを返す

includeとfieldsパラメータへの対応

Laravel13では、JSON:API(フロントエンドとバックエンドのデータ交換方法を定めたオープンな標準仕様)に沿ったレスポンスを、標準機能だけで返せるようになりました。

具体的には、クエリパラメータの?include=author(関連データの取得指定)や?fields[articles]=title(返すフィールドの絞り込み)に対応します。

// ❌ Before:includeやfieldsを自前で解釈する必要があった
public function show(Article $article)
{
    $article->load(request()->has('include') ? ['author'] : []);

    return response()->json([
        'data' => $article,
    ]);
}
// ✅ After:JSON:API Resourceを継承するだけで対応できる
use Illuminate\Http\Resources\JsonApi\JsonApiResource;

class ArticleResource extends JsonApiResource
{
    public function toArray($request): array
    {
        return [
            'title' => $this->title,
            'body' => $this->body,
        ];
    }
}

GET /api/articles/1?include=authorのようなリクエストが来たとき、includeパラメータの解釈やリレーションのロードをフレームワーク側が担ってくれます。

フロントエンドがReactやVueで、必要なフィールドだけを都度絞り込みたいケースでは、通信量を抑えられるので特に相性が良いです。

既存のAPI Resourceとの使い分け

すべてのエンドポイントをJSON:API仕様に寄せる必要はありません。

社内向けの管理画面APIのようにシンプルなJSON形式で十分な場合は、従来のJsonResourceをそのまま使う方が実装コストは低くなります。

外部に公開するAPIで、フロントエンドチームやパートナー企業と仕様を揃えたい場合にJsonApiResourceを検討する、くらいの使い分けが現実的です。

Cache::touch()でTTLだけを延長する

従来のキャッシュ延長方法との違い

キャッシュの有効期限だけを延ばしたいとき、Laravel12までは値を取得して再度putし直す必要がありました。

Laravel13で追加されたCache::touch()を使うと、値の再取得・再保存なしにTTL(有効期限)だけを延長できます。

// ❌ Before:値を取得してから再度putする
$value = Cache::get('user:profile:123');
Cache::put('user:profile:123', $value, now()->addHours(1));
// ✅ After:Cache::touch()でTTLだけ延長する
Cache::touch('user:profile:123', now()->addHours(1));

アクセスの多いキャッシュキーで効果を発揮する

Cache::touch()が特に効くのは、アクセス頻度が高く、値自体はほとんど変わらないキャッシュです。

たとえば会員プロフィールやマスタデータのキャッシュなど、「見られるたびに有効期限だけ延ばしたい」用途に向いています。

従来のget→put方式だと、値のサイズが大きいキャッシュキーではその分だけ無駄な読み書きコストがかかっていました。

Cache::touch()はTTLの更新だけを行うため、Redisなどキャッシュストア側の負荷も抑えられます。

よくあるつまずきポイント・エラー対処

Attributesとプロパティ宣言を混在させて挙動が読めなくなる

一番ハマりやすいのは、同じクラスの中でAttributesとプロパティ宣言を両方書いてしまうケースです。

// ❌ 混在させると、どちらが優先されるか分かりにくくなる
#[Tries(3)]
class SendInvoiceEmail implements ShouldQueue
{
    public $tries = 5;
}

筆者が実際に検証した際、Attributesとプロパティ宣言が両方存在すると意図が伝わりにくいコードになり、レビューで指摘を受けたことがあります。

1つのクラスの中では、Attributes方式かプロパティ宣言方式のどちらかに統一するのがおすすめです。

チームで導入する場合は、新規クラスからAttributes方式に統一するというルールを最初に決めておくと混乱を避けられます。

応用・一歩先の使い方

Queue RoutingとAttributesを組み合わせる

#[Tries(3)]のようなジョブ単体の設定はAttributesで、接続先・キュー名のような「環境ごとに変わりやすい設定」はQueue::route()で管理する、という役割分担がしっくりきます。

ジョブクラス自体の振る舞いはコードに、インフラ寄りの設定は1箇所にまとめておくことで、本番・ステージング環境でキュー構成を変える際もジョブクラスに触れずに済みます。

JSON:API ResourceとCache::touch()を組み合わせる

JSON:API Resourceで返すデータをCacheに乗せておき、アクセスのたびにCache::touch()でTTLを延長する構成も相性が良いです。

頻繁に読まれるが更新頻度は低いAPIエンドポイントであれば、この組み合わせでDBアクセスとキャッシュ書き込みの両方を減らせます。

まとめ

この記事のポイント

  • PHP AttributesはLaravel13でモデル・ジョブの設定を宣言的に書ける新しい構文。従来のプロパティ宣言も引き続き動作するため、混在させずどちらかに統一するのがコツ
  • Queue RoutingはQueue::route()でジョブごとの接続先・キュー名を一元管理できる。キュー構成の変更に強くなる
  • JSON:API Resourcesは?include=?fields[]=といった標準仕様のクエリパラメータに対応できる。外部公開APIで特に有効
  • Cache::touch()は値を再保存せずTTLだけ延長できる。アクセス頻度が高いキャッシュキーで効果が大きい

次に読むべき記事

Laravel12からのアップグレード手順や破壊的変更の注意点は、次回の「Laravel12→13 移行完全ガイド」で詳しく解説します。

Laravel13の全体像をまだ読んでいない方は、シリーズ1本目の「Laravel13とは?Laravel12からの変更点まとめ」もあわせてどうぞ。

タグ: #Laravel #Laravel13 #中級者向け #実践Tips

タイトルとURLをコピーしました