0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PR: フリーランスコネクト株式会社
フリーランスコネクト採用ページ

【2026年9月】Laravel/PHP 今月のまとめ|13.30→13.34、AI SDK と MCP が 1.0、Laravel 14 と PHP 8.6 の予告

0
Posted at

2026年9月の Laravel News を1本にまとめた。コアは 13.30 から 13.34 の5リリース。周辺では Laravel AI SDK と Laravel MCP がそろって 1.0 になり、Laravel 14 と PHP 8.6 の中身も見えてきた。対象は42記事。9月公開の45本から4本(配信とキャンペーンの告知2本、ベンダー自身の寄稿1本、動画連載の紹介1本)を除き、8月31日夜(日本時間)の公開で先月分に間に合わなかった Inertia.js v3.7 を足した。

上から順に読む記事ではなく、表で流し見して、気になったものだけ本文か出典リンクに飛ぶ構成にした。主要なセクションの頭には一覧表を置いたので、そこだけ見て終わりでも構わない。

出典はすべて Laravel News の各記事。バージョン番号やメソッド名は原文に合わせている。

TL;DR

  • コアは5リリース。キューワーカーが止まった理由を出力で読め、落ちた試行も数えられるようになった。queue:work の停止理由出力、JobInterrupted イベント、#[CountCrashesAsExceptions]、JobProcessed の duration。
  • 上げる前に見ておきたい挙動の変更は3か所。Storage::path() がディスクの外へ出るパスに例外を投げ(13.30)、FormRequest の属性が親クラスから引き継がれ(13.33)、requireMorphMap() が読み込み側にも効く(13.34)。
  • コレクションと Eloquent、スキーマに小さな追加。同じ値が続く要素をひとまとめにする chunkBy()、生成カラムを保存直後に読み直す #[Refreshes]、インデックス追加の inplace() と lock()。
  • 13.32 で Mercure のブロードキャストドライバが入った。WebSocket ではなく SSE で動き、FrankenPHP なら内蔵ハブをそのまま使える。
  • Laravel AI SDK と Laravel MCP が 1.0。どちらも破壊的変更があり、直後に 1.0.1 でセキュリティ修正が出ている。
  • Laravel 14 は 2027年Q1 の見込みで PHP 8.4 以上、PHP 8.6 は11月19日に GA 予定。composer update が書き込む前に差分を見せる公式の Laravel Vet(ベータ)も出た。

コア早見表

バージョン 目玉 上げるときの注意
13.30 chunkBy() / queue:work の停止理由出力 / artisan dev のコマンド除外 / sqlsrv: 形式の接続文字列 Storage::path() が、ディスクのルートから出るパスで PathTraversalDetected を投げるようになった
13.31 Queue::totalSize() / JobInterrupted イベント / pivot モデルの chaperone() / assertSentOnce() 系 出典に注意点の記載なし。lazy() と lazyById() が limit() と offset() を無視していた不具合が直っている
13.32 Mercure ブロードキャストドライバ / copyToDisk() と moveToDisk() / キュー停止系メソッドの enum 対応 出典に注意点の記載なし。Str::password() や Str::camel() の不具合修正を含む
13.33 Cache::memo()->tags() / #[Refreshes] / AsCollection::nullable() / インデックスの inplace() / Worker::$killOnTimeout 親クラスの FormRequest に付けた属性が、サブクラスにも効き始める
13.34 #[CountCrashesAsExceptions] / タイムアウト時の SIGALRM 通知 / JobProcessed の duration / queue:flush --queue requireMorphMap() を呼んでいるアプリは、読み込み時にも未登録の *_type で例外が出る

13.28 と 13.29 は Laravel News にリリース記事が無いので、ここでは扱っていない。

Laravel コアの進化(13.30 → 13.34)

13.30:chunkBy() とワーカーの停止理由、Storage::path() のディスク外パス拒否

chunkBy() は、隣り合う要素をキーの値が変わるところで区切るコレクションメソッド。chunkWhile() に「直前の要素と同じか」を判定するコールバックを書いていた定番の用途が、キー名かコールバック1つで済む。キーは data_get() で解決するのでドット記法が通る。チャンク内では、各要素の元の添字(コレクションのキー)が保たれる。

collect([1, 1, 2, 2, 1, 1])->chunkBy(fn ($value) => $value);
// [[1, 1], [2, 2], [1, 1]]

groupBy() と違い、離れた位置にある同じ値はまとめない。そのぶん遅延コレクションでは値が変わった時点でチャンクを流せる。orderBy() した cursor() に繋げば、数百万行を注文単位で処理しても、メモリに載るのは処理中の1注文ぶんで済む。値の比較は ==(緩い比較)で行われる。

queue:work が終了時に停止理由を出力するようになった。Supervisor 配下で数分おきに再起動するワーカーについて、原因がメモリ上限なのか、接続断なのか、デプロイの queue:restart なのかを、リスナーを書かずに出力の最終行で読める。

2026-09-01 13:20:40 Worker STOPPED Memory limit exceeded

--json では reason、exit_code、jobs_processed、memory を持つレコードになる。理由は9種類あり、WorkerStopReason enum に人が読む文言を返す description() が加わった。--quiet と --silent では出ない。OOM キラーや外からの SIGKILL で殺された場合は、イベントを発行するコードが走らないので無言のままだ。

php artisan dev で起動するプロセスを、出どころで絞れるようになった。DevCommands::withoutVendorCommands() と withoutDefaultCommands() で、パッケージが登録したものと、フレームワーク既定のもの(serve、queue:listen、pail、Vite)をそれぞれ外せる。アプリ側で登録したコマンドは残る。only() や except() で名前を並べる方法は、キューや依存パッケージが増えるたびに壊れていた。

DevCommands::withoutVendorCommands();
DevCommands::withoutDefaultCommands();

ほかに入ったもの。

  • SQL Server:PDO_SQLSRV ネイティブの sqlsrv:Server=...;Database=... 形式の接続文字列を正しく解釈する。従来はURLとして読まれ、データベース名が壊れていた。
  • Artisan:Artisan::commandNamed('app:my-command') が、ほかのコマンドを構築せずに1つだけ解決する。未登録なら null。
  • Laravel Cloud のキュー:13.27 の totalPendingSize() 系3メソッドが、管理下のキューを合算した値を返すようになった。SQS はキューを列挙できないため 0 のまま。
  • 修正:route:cache がファサードの参照先を使い捨てのアプリに向けたままにしていた問題(php artisan optimize の途中で Route is not bound. が出る原因)、Request::clamp() が数値でない入力に 500 を返す問題、db:seed --database が例外時に接続を戻さない問題。ワイルドカードバリデーションの高速化は 12.x にもバックポートされた。

上げるときの注意:Storage::path() が、ほかのファイル操作と同じパス正規化を通るようになった。.. を含んでディスクのルートから出るパスを渡すと、文字列を返さず PathTraversalDetected を投げる。これまで Storage::get('../../../.env') は拒否されるのに、Storage::path() は同じ引数でディスク外の実パスを返していた。リクエスト由来の値を Storage::path() に渡しているコードは、アップグレードの時期に関係なく確認しておきたい。13.30 より前では、ディスク外の実パスがそのまま返るためだ。

出典:https://laravel-news.com/laravel-13-30-0

13.31:キュー総数の totalSize() と JobInterrupted イベント

Queue::totalSize() は、接続上のジョブ総数を1回で返す。13.27 の totalPendingSize()、totalDelayedSize()、totalReservedSize() を足したのと同じ値になる。

JobInterrupted イベントは、Interruptible を実装したジョブがワーカーに中断されたときに発火する。後片付けやログ出力をジョブの外のリスナーに置ける。

Event::listen(JobInterrupted::class, function (JobInterrupted $event) {
    // 中断されたジョブの後始末
});

BelongsToMany に chaperone() が付いた。->using(PostTagPivot::class)->chaperone() と書くと、カスタム pivot モデルに定義した BelongsTo を、DBから読み直さずに使える。これまでは、ハイドレーションの時点で両側のモデルが手元にあるのに読み直していた。リレーション名は自動で推測され、chaperone(declaring: 'tag', related: 'post') で上書きできる。カスタム pivot モデルが無ければ何もしない。

メールと通知のフェイクには、「1回だけ送られた」を検証する短縮形のアサーションが入った。

Mail::assertSentOnce(OrderShipped::class);
Notification::assertSentToOnce($user, InvoicePaid::class);

assertQueuedOnce() と assertSentOnDemandOnce() もある。Vite クラスには、開発サーバーのURLを返す devServerUrl() が加わった。

ほかに入ったもの(リリースノートより)。

  • クエリ:lazy() と lazyById() が limit() と offset() を無視していた不具合の修正。ソフトデリートのカラムがテーブルエイリアスで修飾されるようになった。
  • Redis:キュードライバがクラスタ構成でも安全に動くよう修正。phpredis で接続リセットが warning として表に出たとき、コマンドを再試行する。
  • 属性:UsePolicy と UseEloquentBuilder が親クラスからも解決される。
  • 修正:HTTP クライアントのメモリリーク、並行プロセスへコンテキストが伝わらない問題、assertJsonMissingPath() がワイルドカードを無視する問題、wherePivot() のクロージャスコープが pivot テーブルの操作で無視される問題。

出典:https://laravel-news.com/laravel-13-31-0

13.32:Mercure ブロードキャストと copyToDisk()

Mercure のブロードキャストドライバが入った。Mercure は WebSocket ではなく SSE の上で動くリアルタイムプロトコル。ドライバは Kévin Dunglas のコントリビュートによる。config/broadcasting.php に接続を足して使う。

'mercure' => [
    'driver' => 'mercure',
    'url' => env('MERCURE_URL'),
    'public_url' => env('MERCURE_PUBLIC_URL'),
    'secret' => env('MERCURE_JWT_SECRET'),
    'encryption_key' => env('MERCURE_ENCRYPTION_KEY'),
],

FrankenPHP の内蔵ハブなら url と secret は要らない。プレゼンスチャンネルと、エンドツーエンド暗号化の private-encrypted-* チャンネルにも対応する。クライアント側の対応は、対になる Echo へのプルリクエスト(laravel/echo #549)で入る。install:broadcasting コマンドからも Mercure を選べるようになった。

copyToDisk() と moveToDisk() は、ディスクをまたぐコピーと移動を1メソッドにしたもの。読み取りストリームを開いて書き込みストリームへ流す定型コードが要らなくなる。

Storage::disk('local')->copyToDisk('backup', 'reports/report.csv');
Storage::disk('local')->moveToDisk('backup', 'reports/report.csv');
Storage::disk('local')->copyToDisk('s3', 'reports/report.csv', '2026/report.csv');

第3引数は保存先のパス。ディスク名の代わりにファイルシステムのインスタンスも渡せる。

Queue::pause()、Queue::resume()、Queue::pauseFor() が enum を受け付けるようになった。ジョブの Queue / Connection 属性や route()、forward() はすでに対応済みで、それに揃えた形だ。

ほかに入ったもの(リリースノートより)。

  • 文字列:Str::password() が余分な文字を返す問題と、Str::camel() がマルチバイトの先頭文字を小文字にしない問題の修正。
  • コレクション:containsStrict() でクロージャが null の値に一致したとき false を返す問題、collapseWithKeys() が外側のコレクションに文字列キーがあると落ちる問題の修正。
  • スキーマとキャッシュ:hasIndex がインデックス名を小文字に揃えて比較する。Redis のタグ付きキャッシュで、touch 時にタグエントリの有効期限が同期されない問題も直った。
  • Eloquent:違反検知のコールバックに例外が渡されるようになった。Factory::raw() に件数 0 を渡したときの挙動も修正。

出典:https://laravel-news.com/laravel-13-32-0

13.33:タグ付きメモ化キャッシュと Refreshes 属性

Cache::memo() がタグに対応した。同じリクエストの中で同じタグ付きの値を何度読んでも、キャッシュストアへの往復は初回の1度だけになる。can() や @can のたびに読まれる権限のような値に向く。

Cache::memo()->tags(['permissions'])->get("permissions:{$user->id}");

put() や forget() などの書き込みは、ストアに書いたうえでメモ化した値を捨てる。flush() はタグごとメモ化分も消す。メモ化した値はリクエストやジョブの開始時にリセットされる。カウンタのように、ほかのプロセスが途中で書き換える値には向かない。

#[Refreshes] 属性は、モデルの作成や更新の直後に、指定したカラムだけをDBから読み直す。storedAs や virtualAs の生成カラム、トリガーやDBのデフォルトが入れる値は、これまで refresh() を呼ぶまでモデル上で null か古い値のままだった。

#[Refreshes('total')]
class Order extends Model
{
    protected $fillable = ['subtotal', 'tax'];
}

読み直しは指定カラムだけの SELECT 1本で、書き込み接続で走る。created や updated イベントより前に実行されるので、オブザーバからも計算後の値が読める。属性を使わないなら $refreshes プロパティで同じ指定ができる。書き込みのたびに1クエリ増えるので、直後に読むカラムだけを並べるのがよさそうだ。

AsCollection と AsArrayObject に nullable() が付いた。AsCollection::nullable() と書くと、null を代入したときにDBの NULL が入る。これまではJSON文字列の "null" が入り、whereNull() に当たらなかった。オプトインなので、付けなければ従来の挙動のまま。

インデックスと外部キーの操作には inplace() と lock() が付いた。MySQL のマイグレーションで ALGORITHM=INPLACE と LOCK=NONE を要求でき、テーブルを止める再構築に落ちるのを避けられる。

$table->index('foo', 'foo_index')->inplace()->lock('none');

対象は index()、unique()、primary()、fullText()、spatialIndex()、foreign()。カラム定義にある instant() と同じ発想だ。

ほかに入ったもの。

  • Worker::$killOnTimeout:false にすると、タイムアウトしたジョブでワーカープロセスごと殺す代わりに TimeoutExceededException を投げる。ジョブは後片付けができ、ワーカーは動き続ける。handle() を広い try/catch で包んでいるジョブは、この例外を握りつぶしうる。SIGKILL の前に走るフック Worker::killUsing() も入った。
  • mockArtisan() と realArtisan():$this->artisan() が兼ねていた2つの役割を分けたテストヘルパー。前者は常に期待値を書くための PendingCommand を返し、後者は常にコマンドを実行して終了コードを int で返す。$mockConsoleOutput の切り替えが要らなくなる。
  • リリースノートより:valkey:// と valkeys:// プロトコルのサポート、BelongsToMany の createQuietly() と createManyQuietly()、DevCommands の order()、PostgreSQL 接続のサーバーオプション、install:broadcasting の --pretend。

上げるときの注意:FormRequest の属性が親クラスから引き継がれるようになった。PHP は属性を継承しないので、共通の親リクエストに付けた #[StopOnFirstFailure] や #[FailOnUnknownFields] は、これまでサブクラスで無視されていた。親クラスに属性を付けているアプリでは、上げた時点からサブクラスにも効き始める。

出典:https://laravel-news.com/laravel-13-33-0

13.34:ワーカーのクラッシュを maxExceptions に数える

#[CountCrashesAsExceptions] は、ワーカーごと落ちた試行を例外1回として数えるジョブ用の属性。例外を投げたジョブは $maxExceptions に数えられるが、メモリ不足のキルやセグメンテーション違反、コンテナの停止でワーカーが落ちた試行は数えられなかった。$tries ではなく retryUntil() を使うジョブは、期限が来るまでワーカーを落とし続けることがあった。

#[MaxExceptions(3), CountCrashesAsExceptions]
class ProcessPodcast implements ShouldQueue
{
    // ...
}

public $countCrashesAsExceptions = true; と書いても同じ。ワーカーは対象ジョブの開始時にキャッシュキーを書き、試行が終わると消す。次の試行でキーが残っていれば、前回は落ちたと判断する。maxExceptions の指定が必須で、試行ごとにキャッシュ呼び出しが2回増えるためオプトインになっている。

Interruptible を実装したジョブは、タイムアウト時に SIGALRM を受け取るようになった。これまで SIGTERM などはジョブに渡されていたが、タイムアウトはジョブを呼ばずにワーカーを殺していた。interrupted(int $signal) の中で SIGALRM を見れば、失敗扱いになる前に進捗を保存できる。13.31 の JobInterrupted イベントもここで発火する。

JobProcessed イベントに duration プロパティが加わった。単位はミリ秒で、小数2桁に丸めた float。JobProcessing と対にして開始時刻を自前で持つ必要がなくなる。ワーカー以外から発火した場合は null。

Event::listen(function (JobProcessed $event) {
    Log::info("{$event->job->resolveName()} took {$event->duration}ms");
});

queue:flush には --queue オプションが付いた。外部APIの障害で失敗ジョブが積み上がったとき、影響を受けたキューのぶんだけ消せる。--hours と組み合わせれば直近の失敗は残せる。

php artisan queue:flush --queue=sftp-sync --hours=48

ほかに入ったもの。

  • Schema::getColumn():1カラムぶんの定義だけを返す。Schema::getColumn('users', 'email')['type_name'] のように読め、カラムが無ければ空配列。
  • assertDatabaseCount():テーブル名かモデルクラスと件数の配列を受け取り、複数テーブルを1回で検証できる。
  • enum 対応:App::environment()、スケジューラの environments()、@env ディレクティブ、Queue::isPaused()。これまで environments() に enum を渡すと、そのタスクは一度も実行されなかった。
  • 修正(リリースノートより):Number::parseInt() が32ビットの範囲を超える値で false を返す問題、trans_choice() が負数で複数形を誤る問題、Number::format() などが -0 を返す問題、whereNot() に配列条件を渡したときの二重否定、リトライ時にマルチパートリクエストのストリームが失われる問題、30日を超える Memcached ロックが即時に切れる問題。

上げるときの注意:Relation::requireMorphMap() が読み込み側にも適用される。有効にしていると、保存時だけでなく morphTo の読み込み時にも、モーフマップに無い *_type の値で ClassMorphViolationException が投げられる。遅延ロードでも Eager ロードでも同じ。requireMorphMap() を呼んでいないアプリには影響しない。古いデータにクラス名のままの *_type が残っていないか、上げる前に見ておくと安全だと思う。

出典:https://laravel-news.com/laravel-13-34-0

機能別の解説記事に飛ぶ

コアの機能のうち5つには、Laravel News 側に単体の解説記事がある。実装するときはこちらが早い。

対象 解説記事 内容
13.30 chunkBy() groupBy() との違い、遅延コレクションでのストリーム処理、緩い比較と、キーを求めるコールバックが1要素につき2回呼ばれる点
13.30 queue:work の停止理由 9種類の理由と終了コードの対応表、--json を jq で絞る例
13.30 artisan dev のコマンド除外 既定の4プロセスと、dev:list で起動対象を確認する方法
13.33 Refreshes 属性 読み直しが走る書き込みの一覧、モデルイベントとの順序、refresh() との使い分け
13.33 タグ付きメモ化キャッシュ 書き込みとフラッシュ時の挙動、向く値と向かない値

Laravel AI SDK と Laravel MCP が 1.0

AIまわりの公式パッケージ2つが、9月にそろって安定版になった。どちらも 0.x からの破壊的変更を含み、公開直後にセキュリティ修正が出ている。

パッケージ 1.0 の目玉 上げるときの注意
Laravel AI SDK 1.0 分類(Classification)、Vercel Chat と AG-UI のストリーミング、承認待ちツール 会話の保存形式などに破壊的変更。1.0.0 に SSRF があり 1.0.1 で修正
Laravel MCP 1.0 MCP 2026-07-28 対応、検索できるツールカタログ、キャッシュヒント、ステートレス化 ヘッダ検証のミドルウェアが追加。OAuth リダイレクト検証の不備は 0.9.6 と 1.0.1 で修正

Laravel AI SDK 1.0:分類とフロント向けストリーミング

laravel/ai は、AIプロバイダを1つのAPIで扱う公式パッケージ。2月に発表され、今回 1.0 になった。

新しく加わったのが分類(Classification)。テキスト、画像、音声、埋め込みと並ぶ機能で、サポートチケットの振り分けや問題のあるコメントの検出のように、短い問いにその場で答えさせたい判定に使う。答えは質問ごとに型の付いた値で返る。TypeSafe の Jev モデルで動き、対応プロバイダは今のところ TypeSafe と OpenRouter。質問の型には Boolean、Choice、0.0 から 1.0 を返す Score がある。「はい」か「いいえ」で答える1問だけなら Str のマクロで足りる。

Str::of($message)->decide('Is this spam?');

フロントエンド向けには、Vercel Chat と AG-UI の2プロトコルでリクエストを読み、ストリームを返せるようになった。Vercel::chat($request) を使ったルートで、新着メッセージの読み取り、会話履歴の更新、ユーザーが出したツール承認の処理までをまかなえる。CopilotKit のような AG-UI クライアントには usingAgentUserInteractionProtocol() を使う。

ほかに 1.0 に含まれるもの。

  • 承認待ちツール:7月に先行して入っていた機能。Approvable を実装したツールは、誰かが承認するまでエージェントを止める。承認、理由を付けた却下、引数を直してからの実行ができる。
  • ステップ単位のミドルウェア:エージェントミドルウェアが、プロンプトごとではなく生成ステップごとに走る。PendingStep に withModel や withoutTools を呼び、たとえば高価なツールを1度使ったら外せる。
  • プロバイダツール:使用頻度の低いツールを遅延ロードする ToolSearch(OpenAI と Anthropic)と、プロバイダのサンドボックスでコードを動かす CodeExecution。

上げるときの注意:破壊的変更は、会話の保存形式、エージェントミドルウェア、トークン使用量、ストリームプロトコルに集まっている。

  • 会話の保存形式:メッセージは steps というJSONカラム1本に、往復ごとの記録を持つ形に変わった。tool_calls や tool_results に生SQLを投げていれば書き換えが要る。デプロイ前に1度流すバックフィル用マイグレーションが、アップグレードガイドにある。
  • トークン使用量:promptTokens と completionTokens は、inputTokens と outputTokens に改名された。
  • 移行の補助:Laravel Boost を入れていれば、/upgrade-ai-sdk-v1 スラッシュコマンドが手順を1つずつ案内する。

セキュリティ修正:1.0.0 の Vercel アダプタと AG-UI アダプタには、クライアントが指定したURLを検証せずに取得する SSRF があった(深刻度 Moderate)。1.0.1 で修正済み。どちらかのアダプタを信頼できないクライアントに公開しているなら、上げておきたい。告知記事は日本時間で10月1日の公開なので、詳しくは来月分で扱う。

出典:https://laravel-news.com/laravel-ai-sdk-1-0

Laravel MCP 1.0:新プロトコルとツール検索

laravel/mcp は、アプリのツールやデータをAIアプリケーションに使わせる MCP サーバーを、Laravel で書くための公式パッケージ。1.0 で MCP リビジョン 2026-07-28 に対応した。最初の initialize の往復が server/discover に置き換わる。initialize で繋いでくる従来のクライアントも引き続き動く。

目玉は検索できるツールカタログ。ToolSearch::class => [...] に入れたツールは一覧に載せず、エージェントが search_tools で探して execute_tools で実行する。ツール定義がコンテキストウィンドウを食うのを抑えられる。

protected array $tools = [
    CurrentWeatherTool::class,

    ToolSearch::class => [
        HistoricalWeatherTool::class,
        WeatherAlertsTool::class,
    ],
];

ほかに 1.0 に含まれるもの。

  • キャッシュヒント:#[Cacheable(ttlMs: 60_000, scope: CacheScope::Public)] で、クライアントがレスポンスを再利用できる期間と共有範囲を伝える。メソッド単位の上書きは cacheHints()。ツール呼び出しはキャッシュ対象外。
  • ステートレス化:サーバーは各リクエストを独立に処理する。MCP-Session-Id ヘッダ、Request::sessionId()、SessionInitialized イベントは削除された。
  • OAuth:PKCE 対応が必須になった。client_id を HTTPS のURLにする Client ID Metadata Documents にも対応し、従来の動的クライアント登録は新プロトコルで非推奨になっている。

上げるときの注意:0.9 から上げると、Mcp::web() で登録した全ルートに ValidateMcpHeaders ミドルウェアが掛かる。

  • 必要なヘッダ:新プロトコルの POST には、ボディと一致する MCP-Protocol-Version と Mcp-Method が要る。tools/call などには Mcp-Name も要る。不一致は HTTP 400。
  • テスト:postJson() でリクエストを送るテストにも、同じヘッダと params._meta のフィールドが必要になる。
  • OAuth クライアントの保存先:Client ID Metadata Documents を使うと $token->clientSecret が null になるので、カラムは null を許しておく。

セキュリティ修正:OAuth のリダイレクトURL検証に不備があり(深刻度 Low)、0.9.6 と 1.0.1 で修正された。1.0.0 のままなら 1.0.1 へ。

出典:https://laravel-news.com/laravel-mcp-1-0

Laravel 14 と PHP 8.6 の予告

来年のメジャーと今年の PHP について、Laravel News がまとめ記事を出した。どちらも確定前の内容を含む。

対象 時期 要点
Laravel 14 2027年Q1 の見込み PHP 8.4 以上。Route::query() や $user->authorize() が入り、挙動の変わる箇所も判明
PHP 8.6 2026年11月19日に GA 予定 部分関数適用、clamp()、Time\Duration、セッション既定値の変更
リリースサイクルの解説 毎週と年1回 毎週のマイナー、年1回のメジャー、バグ修正18か月とセキュリティ修正2年

Laravel 14:master ブランチから見える変更

Laravel 14 について分かっていることは、master ブランチにマージ済みの変更から次期メジャーを追う記事。リリースは 2027年Q1 の見込みだが、リリース日も機能一覧も公式には未発表で、内容は変わりうる。PHP の最低バージョンは 8.4 で、Symfony 8 の要件に合わせたもの。バグ修正は 2028年Q3 まで、セキュリティ修正は 2029年Q1 までの見込み。

追加されるもの。

  • Route::query():HTTP の QUERY メソッドを受けるルート。
  • $user->authorize():Gate::forUser($user)->authorize() を短く書ける。失敗すると AuthorizationException を投げる。
  • report() のコンテキスト:report($e, ['order_id' => $order->id]) のように配列を添えられる。
  • Storage::fake('ondemand'):Storage::build() で作るオンデマンドディスクをテストで差し替える。
  • orWhereKey() と orWhereKeyNot():whereKey() 系の4メソッドはサブクエリも受け取る。

新機能の大半は 13.x の毎週のリリースに入る。14 まで待つのは、コントラクト(インターフェース)にメソッドを足すもの、シグネチャを変えるもの、既存の挙動を変えるものだ。

挙動やシグネチャが変わるものは次のとおり。

対象 Laravel 13 Laravel 14
Queue::pause() 系の引数順 Queue::pause('redis', 'emails')。接続が先 Queue::pause('emails')。キューが先で、接続は省略できる
lazy() と chunk() ビルダーを書き換えるので、同じビルダーを使い回すと結果が狂う(lazy(2) のあとの count() が 0 になる) ビルダーを変更しない
findOr() にIDの配列 コールバックが呼ばれず、見つかった分だけ返る findOrFail() と同じ条件でコールバックが呼ばれる
Cache::has() と Cache::forget() に配列 has() は常に true、forget() はキーを消さない has() は全キーがあるときだけ true、forget() は全キーを消す
MassPrunable とソフトデリートの併用 ソフトデリート済みの行は残る ソフトデリート済みも強制削除する。従来どおりにするなら withoutTrashed() を足す
ExceptionHandler::report() report(Throwable $e) report(Throwable $e, array $context = [])。自前のハンドラで上書きしていれば引数の追加が要る

PHP 8.6:部分関数適用と clamp()

PHP 8.6 の新機能まとめによると、8.6 のフィーチャーフリーズは9月22日、GA は11月19日の予定。目玉は部分関数適用で、? が後から埋める引数1つ、... が残り全部を表す。

$makeSlug = str_replace(' ', '-', ?);

$makeSlug('Hello World'); // Hello-World

ほかに入るもの。

  • clamp():値を範囲に収める。clamp(101, min: 0, max: 100) は 100。min(max(...)) の書き間違いをなくせる。
  • Time\Duration:時間の長さをナノ秒精度で表す final readonly クラス。単位ごとのファクトリと算術メソッド、比較演算子に対応。
  • 言語仕様:readonly プロパティに既定値を書ける。引数に直接 DocComment を書け、ReflectionParameter::getDocComment() で取れる。enum に __debugInfo() を定義できる。
  • 標準ライブラリ:epoll や kqueue を統一的に扱う Io\Poll、共通の SortDirection enum、ストリームのエラーを例外にできる error_mode、URI 拡張のビルダークラス。

上げるときの注意:新規インストールの php.ini で、session.use_strict_mode と session.cookie_httponly の既定が 1 に、session.cookie_samesite が Lax に変わる。Laravel は自前でセッションクッキーを管理するので大半のアプリは影響を受けないが、PHP ネイティブのセッションに頼っているコードは確認が要る。

リリースサイクル:サポート期間の読み方

Laravel のリリースサイクル解説は、バージョン番号の読み方とサポート期間を1ページにまとめた記事。フレームワークはほぼ毎週、たいてい火曜にタグが打たれ、機能追加ならマイナー、バグ修正だけならパッチが上がる。メジャーは年1回で第1四半期ごろ。バグ修正は18か月、セキュリティ修正は2年で、LTS はもう無い。

Laravel 12 のバグ修正は 2026年8月13日に終わっていて、セキュリティ修正は 2027年2月24日まで。新メジャーが出てから旧版のバグ修正が続くのは数か月なので、アップグレードの計画は2年ではなくこの短いほうの期間に合わせることになる。名前付き引数は後方互換の保証対象外で、マイナーでも引数名が変わりうる。

注目パッケージ

パッケージ早見表(24本)

気になった行だけ、下の該当セクションか出典リンクへ。

セクション パッケージ 何ができるか
公式ツール Laravel Vet composer update が書き込む前に依存の差分を見せ、信頼済みを vet.json に記録する
公式ツール Laravel Telescope 5.24.0 記録済みエントリをターミナルから一覧、詳細表示する(JSON 出力あり)
公式ツール Inertia.js v3.7 <Form> の送信を、アンマウント時やボタンから中断できる
公式ツール Inertia DevTools の Firefox 版 ページ遷移(visit)のタイムラインと props を Firefox の DevTools で見る
エディタ JetBrains Air JetBrains IDE の中で複数のAIコーディングエージェントを動かす
データベース Compoships 複数カラムの組で Eloquent のリレーションを張る
データベース Difflock マイグレーションを実DBのスキーマとテーブルサイズに照らして検査する
データベース Vacuum PostgreSQL の統計から問題と修正SQLを出し、100点満点で採点する
データベース Elastic Bridge Elasticsearch と OpenSearch を Eloquent 風のAPIで検索する
データベース Fast Excel 5.x 大きな Excel/CSV を遅延読み込みし、数式に見える値を文字列で書き出す
課金と業務ルール Laravel Rulebook 時期で変わる業務ルールを期間つきのクラスで持ち、判定の理由を残す
課金と業務ルール Tashil サブスクのプランと機能ごとの利用上限を管理する(決済は別)
課金と業務ルール PayZephyr 8つの決済プロバイダを1つのAPIで扱い、失敗時に別プロバイダへ切り替える
運用とテスト Laravel Scalpel デプロイ済みアプリのファイルから侵入の痕跡を探す
運用とテスト Health for Laravel Kubernetes のプローブ別ヘルスチェックと Prometheus メトリクスを出す
運用とテスト Fuzz Pest 5 のテストの中でカバレッジ誘導型のファジングを走らせる
運用とテスト Mailbox for Laravel 送信メールをアプリ内の受信箱で確認し、描画後の内容をテストする
BladeとCMS Forte Blade を構文木にパースし、検索、一括書き換え、規約チェックに使う
BladeとCMS Quick Blade macOS の Finder で Blade の描画結果をプレビューする
BladeとCMS MKSine Filament 4/5 に載せるCMS。ページビルダー、テーマ、プラグイン機構つき
BladeとCMS Statamic Sidecar 既存の Markdown サイトを、取り込まずに Statamic の管理画面から編集する
開発環境 Fresh Package テスト、静的解析、CI が最初から入った Laravel パッケージの雛形
開発環境 Super Stack Web、Filament 管理画面、ネイティブアプリ、MCP サーバーを1つにしたスターターキット
開発環境 Bifrost の1周年アップデート NativePHP のビルドサービスに MCP サーバーと自動ワークフローが入った

公式ツールとエディタ

  • Laravel Vet:Laravel 公式の Composer プラグイン。composer update が vendor/ に書き込む前に、入ってくるコードの差分を見せる。信頼したパッケージはバージョンとファイル全体のハッシュで vet.json に記録され、次回は変わった分だけ聞かれる。差分の確認は手元のコーディングエージェント(Claude Code、Codex、Gemini、OpenCode)に渡せて、結果は PASS / FAIL / WARN / SKIP で返る。未信頼のパッケージがあると非ゼロで終了するのでCIを落とせる。PHP 8.4 以上。まだベータ。
composer require laravel/vet --dev
./vendor/bin/vet --init
  • Laravel Telescope 5.24.0:記録済みのエントリをターミナルから読む telescope:list と telescope:show が入った。ダッシュボードを開かずに、リクエストや例外、ジョブ、クエリを探してバッチごと確認できる。latest:exception のように直近のエントリを指定でき、バッチの表では閾値を超えたクエリに SLOW、同じSQLパターンの繰り返しに DUP が付く。--json はスクリプトやコーディングエージェント向けで、Laravel Boost 用のデバッグスキルも同梱された。
php artisan telescope:show latest:request --type=query,cache
  • Inertia.js v3.7:<Form> コンポーネントが送信中のリクエストを中断できるようになったリリース。cancelOnUnmount を付けると、フォームがアンマウントされた時点で中断する。モーダルを閉じても裏でアップロードが走り続ける問題への対処で、既定は false。スロットプロップなどから cancel も呼べる。usePoll は実行中かどうかを表す polling を返すようになった。Svelte では分割代入するとリアクティビティが切れるので poll.polling で読む。

  • Inertia DevTools の Firefox 版:Inertia 公式のブラウザ拡張が Firefox でも使えるようになった。機能は Chrome 版と同じで、ページ遷移(visit)のタイムライン、deferred や optional のバッジが付いた props のツリー、リクエストとレスポンスのヘッダと本文、対応するルートとコントローラをパネルで見られる。エディタの該当行へ飛ぶリンクもある。認証ヘッダや CSRF トークンは表示前に伏せられ、記録は手元のマシンに留まる。

  • JetBrains Air:AIコーディングエージェントを個人、チーム、組織で動かして管理するための JetBrains の製品群。IDE 用の無料プラグイン(パブリックプレビュー)は、PhpStorm などの中で Claude Agent、Codex、Junie、Copilot、OpenCode を複数セッション同時に走らせ、差分を IDE のツールでレビューできる。ほかに、クラウド環境でタスクを回す Air Teams(アーリーアクセス)と、権限や支出上限、利用状況の分析を担う Air Governance(旧 JetBrains Central)がある。

データベースと検索

  • Compoships:Eloquent のリレーションを複数カラムの組で張れるようにするパッケージ。両側のモデルに Compoships トレイトを付けると、hasOne、hasMany、belongsTo、belongsToMany がキー名の代わりにカラムの配列を受け取る。hasMany() に where() を足す回避策は、Eager ロードで誤った行を返す。Compoships はその置き換えになる。$compositeKey を宣言すれば、save() や delete() の WHERE も全キーカラムで絞られる。PHP 8.2、Laravel 12 か 13。
return $this->hasMany(
    OrderLine::class,
    ['company_code', 'order_no'],
    ['company_code', 'order_no']
);
  • Difflock:マイグレーションを、これから変更する実データベースに照らしてレビューする開発用パッケージ。マイグレーションのソースは実行せずに読み、実スキーマとテーブルサイズから危ない変更を挙げる。データのあるテーブルへの NOT NULL カラム追加、dropColumn()、リネーム、モデルイベントを通らない cascadeOnDelete() など。スキーマをJSONに記録してドリフトを検出する difflock:diff、検査してから migrate に渡す difflock:migrate、MCP サーバーもある。PHP 8.3、Laravel 12 か 13。
php artisan difflock:lint
php artisan difflock:check --ci
  • Vacuum:PostgreSQL の統計ビューを読んで、問題とそれを直すSQLを並べる監視パッケージ。13個のアドバイザルールの結果から、100点満点のヘルススコアを出す。画面は /vacuum か Filament 4/5 のプラグイン。vacuum:check --fail-on=warning でCIを落とせ、vacuum:lint はインデックスの無い外部キーなどを指摘する。1.2.0 の要件は PostgreSQL 14、Laravel 11 以上。ダッシュボードは既定で local 環境でしか開かない。

  • Elastic Bridge:Elasticsearch と OpenSearch を Eloquent 風のAPIで検索するパッケージ。インデックスごとに「ブリッジ」クラスを定義し、JSON の DSL を手書きせずにメソッドチェーンで全文検索とフィルタを組む。キャスト、アクセサとミューテタ、バルクインデックス、集計、search_after によるカーソルページネーションに対応。fake() を使えばクラスタ無しで生成クエリをテストできる。要件は PHP 8.2 か 8.3、Laravel 10 から 12、Elasticsearch 8.x か OpenSearch 2.x。

$rooms = HotelRoom::asBoolean()
    ->mustMatch('city', 'accra')
    ->filterByTerm('code', 'usd')
    ->filterByRange('price', 500, 'lte')
    ->get(['name', 'price', 'code']);
  • Fast Excel 5.x:OpenSpout ベースで行の読み書きに絞った Excel/CSV パッケージ。5系の最近のリリースで、大きなファイルの取り込みに向いた機能が増えた。importLazy() は行を LazyCollection で返し、全件をメモリに載せずに処理できる(5.12)。sheet() でシートを選び、onlyColumns() で列を絞れる(列の絞り込みは 5.16)。escapeFormulas() は = や @ で始まる値を数式でなく文字列として書き出す(5.17)。PHP 8.0 以上、Laravel 6 から 13。

課金と業務ルール

  • Laravel Rulebook:時期によって変わる業務ルールを、有効期間つきのPHPクラスとして並べておくパッケージ。各ルールが from() や between() で適用期間を宣言し、ある時点で解決すると priority() で勝者が1つ決まる。去年の返金規定を今年の規定の隣に残せる。評価した全ルールについて状態(applicable、does_not_apply、outside_validity)と理由が返り、snapshot() で判定をJSONに固めてレコードと一緒に保存できる。PHP 8.3、Laravel 12 か 13。

  • Tashil:サブスクリプションのプランと、機能ごとの利用上限をDBで管理するパッケージ。決済はしない。Stripe や Paddle などで課金し、その結果を Tashil に記録する。useFeature() は上限チェックと加算を1クエリで行うので、同時リクエストでも上限を超えない。上限の80%で UsageLimitWarning イベントが飛ぶ。トライアル、アップグレード、期末のダウングレード、請求書、MRR や解約率の集計、@feature ディレクティブもある。PHP 8.2 以上、Laravel 10 から 13。

if (! $team->useFeature('episode-uploads')) {
    // 今月の上限に達している
}
  • PayZephyr:8つの決済プロバイダを、同じ Payment ファサードから扱えるようにする決済パッケージ。対応は Paystack、Stripe、PayPal、Flutterwave、Square、Monnify、OPay、Mollie。既定のプロバイダが失敗したときに別のプロバイダへ切り替えるフェイルオーバー、二重課金の防止、署名検証つきの Webhook、サブスクリプション、全額と一部の返金を備える。返金はプロバイダによっては後から確定するので、$refund->isPending() で保留中かどうかを確かめる。

運用とテスト

  • Laravel Scalpel:デプロイ済みアプリのファイルシステムから侵入の痕跡を探すスキャナ。public/ や storage/ に置かれたPHPファイル、eval(base64_decode(...)) のような難読化、.htaccess や .user.ini の不審なディレクティブ、.env の異常を調べ、scalpel:baseline で取ったスナップショットとの差分も出す。PHP 8.2 以上、Laravel 10 から 13。ビューをキャッシュする環境では、コンパイル済みビューが検出に引っかかりやすい。

  • Health for Laravel:Kubernetes の3種類のプローブに、別々のエンドポイントを用意するヘルスチェックパッケージ。/health(liveness)、/health/ready、/health/startup のそれぞれに、どのチェックを割り当てるかを設定ファイルで決める。組み込みチェックはDB、キャッシュ、キュー、ストレージ、Redis、スケジューラなど10種類。/health/metrics は Prometheus 形式で、コンテナ内では cgroup の上限からメモリを読む。2.0.0 は PHP 8.3 と Laravel 11 から 13。

  • Fuzz:Pest 5 のテストの中でカバレッジ誘導型のファジングを走らせるパッケージ。渡した文字列を nikic の PHP-Fuzzer が変異させ、新しい実行経路に届いた入力を残しながら探索する。Xdebug も --coverage も要らない。失敗した入力は .pest/fuzz-crashes/ に保存される。対象を呼ぶ関数は test() の外に定義する。別プロセスで実行されるので、Pest が生成するテストクラスに頼れないためだ。PHP 8.4 以上。

fuzz($target)
    ->seed(['100/60s', '5/1s', '1000/3600s'])
    ->withDictionary(['/', 's', '0', '1'])
    ->runs(2000)
    ->maxLen(16)
    ->run('rate-limit-parser');
  • Mailbox for Laravel:送信メールを捕まえて、アプリ内の /mailbox に表示する開発用パッケージ。別のメールサービスやプロセスは要らず、php artisan mailbox:install のあと MAIL_MAILER=mailbox にすれば動く。描画後のメールを assertSeeInHtml() や assertHasAttachment() で検証するテストAPIもある。PHP 8.3 以上、Laravel 10 から 13。本番では Mailbox が既定で無効になる。MAIL_MAILER=mailbox を残したままだと、メールはどこにも送られない。

BladeとCMSと開発環境

  • Forte:.blade.php を型付きの構文木にパースし、検索して、書き換えたテンプレートを出力するライブラリ。prettier-plugin-blade の作者 John Koster 製。sed と違い、文字列やコメントの中の一致を拾わない。コンポーネントの使用箇所の集計、数百ファイルへの同じ編集、「POST のフォームに @csrf が無い」のような規約違反をテストで落とす用途に向く。XPath も使え、Blade の構文は forte:if のような要素になる。PHP 8.2、Laravel 10 から 13。
$missing = Forte::parseFile($file->getPathname())
    ->xpath('//form[@method="POST"][not(.//forte:csrf)]')
    ->count();
  • Quick Blade:.blade.php の描画結果をプレビューする macOS の Quick Look 拡張。Finder でファイルを選んでスペースキーを押すと出る。プロジェクトをディスクから読むので、開発サーバーもDBもネットワークも要らない。レイアウトを解決し、コンパイル済みのCSSをインライン化し、echo にはダミーデータを入れる。Flux と Livewire のタグにもスタイルが当たる。導入は brew install --cask timgavin/tap/quick-blade。

  • MKSine:Filament の管理画面にコンテンツ層を足すCMSパッケージ。固定ページ、投稿、カテゴリ、ブロック式のページビルダー、テーマ、メニュー、メディアライブラリ、インストールと有効化のライフサイクルを持つプラグイン機構が入っている。要件は PHP 8.2、Laravel 11、Filament 4 か 5(Filament 5 では Laravel 11.28 以上)。Filament チームではなくコミュニティ製で、現行は v1.5.1。プラグイン登録より先にインストーラを走らせると権限が作られないなど、導入手順に順序の罠がある。記事は、本番投入の前にソースを読むよう勧めている。

  • Statamic Sidecar:静的サイトジェネレータの Markdown を、Statamic のコントロールパネルから編集できるようにする新製品。コレクションへの取り込みはせず、ファイルもフロントマターもフォルダ構成も元のまま。サイトの描画は元のジェネレータが続ける。ドラッグで並べ替えるコンテンツツリー、公開フォーム、ライブプレビューが使える。ドキュメントサイトやナレッジベースで、開発者以外にも編集してもらう用途が挙げられている。

  • Fresh Package:Laravel パッケージを作り始めるためのスケルトン。PHPUnit、Larastan、Rector、Pint、Testbench の workbench/ アプリ、PHP 8.3 から 8.5 と Laravel 12/13 のテストマトリクスを回す GitHub Actions、release-please までが最初から入る。パッケージを入れた側のアプリに配る Laravel Boost スキルの雛形も付く。次のコマンドでウィザードが始まる。

composer create-project sunchayn/fresh-package my-package
  • Super Stack:NativePHP チームのスターターキット。Webアプリ、Filament 5 の管理画面、ネイティブモバイルアプリ、MCP サーバーを1リポジトリに収めている。ホーム画面は NativePHP v4 の SuperNative で、1つの Blade テンプレートが iOS と Android ではネイティブUI、ブラウザではHTMLになる。Laravel 13 向けで、PHP 8.4 以上が要る。同梱の MCP サーバー(/mcp/superstack)には認証が設定されていないので、デプロイ前に足す必要がある。
laravel new my-app --using=nativephp/superstack
  • Bifrost の1周年アップデート:NativePHP チームのビルド配布サービス Bifrost が1周年を迎え、成功ビルドは1万件に達した。節目に6つの更新が入っている。エージェントからビルドを開始できるリモート MCP サーバー、プルリクエストやタグ作成で走る自動ワークフロー、iOS の証明書と Android のキーストアを任せられるマネージド署名、失敗したビルドのAI診断、Webサイトの刷新、モノレポ対応。

エコシステムの動き

  • Taylor が大半の Laravel パッケージで GitHub Issues を無効化:Taylor Otwell が、Laravel のオープンソースパッケージの大半で Issues を止めた。バグに当たった人には、コーディングエージェントに内容を伝えてPRを開くよう求めている。コードの質は後から直せるし、PRそのものが問題の記録になる、という考えだ。対象はパッケージで、フレームワーク本体のリポジトリは含まない。記事によれば Symfony は逆に、まず Issue を受け付ける進め方を試している。
  • Laracon Archive:Laracon の講演を検索できるアーカイブサイト。2013年の第1回から14年ぶん、Laracon US、EU、Online、AU、India の講演626本と登壇者287人を収録している。Prince John Santillan による独立したプロジェクトで、Laravel や各 Laracon の運営とは関係が無い。動画そのものは各カンファレンスの YouTube に置かれたままで、サイトはそれらへの索引になっている。
  • Laravel Live Denmark 2026 の講演動画:全17本が YouTube のプレイリストで公開された。PHP のジェネリクス、Inertia、NativePHP、パッケージ開発、セキュリティ、AIが題材。Freek Van der Herten のパッケージ設計パターン、Ondřej Mirtes の PHPStan とコーディングエージェント、Taylor Otwell と David Heinemeier Hansson の対談などが、見始める1本として挙げられている。

今月のトレンド

  • キューは、なぜ止まったかまで追えるようになった。 8月に入ったのは、キューを止める機能と流し先を付け替える機能だった。9月は停止理由の出力、JobInterrupted、タイムアウト時の SIGALRM、クラッシュを数える属性と、止まった理由を記録に残す機能がそろった。メモリ上限や接続断で再起動を繰り返すワーカーは、最終行で原因が読める。OOM キラーに殺された試行は停止理由には出ないが、#[CountCrashesAsExceptions] で回数に数えて打ち切れる。
  • エージェントに読ませる前提の出力が増えた。 telescope:show --json、dev:list --json、Difflock と Bifrost の MCP サーバー、Vet のエージェントレビュー。Taylor が Issues を止めてPRを求めたのも同じ流れにある。
  • 問題が本番に入る前に止める道具が並んだ。 依存の差分は Vet、マイグレーションは Difflock、Blade の規約違反は Forte、パーサの想定外入力は Fuzz。どれもCIやテストを失敗させて止められる。

まとめ

今月ぶんで最初に手を付けるなら、Storage::path() にリクエスト由来の値を渡している箇所の確認だ。13.30 より前ではディスクの外のパスがそのまま返るので、アップグレードがまだ先でも見ておく価値がある。AI SDK の 1.0.0 は 1.0.1 へ。MCP は 1.0.0 なら 1.0.1、0.9.5 以下なら 0.9.6 へ。詳細は各出典リンクから。来月も続ける。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?