ニュース

Laravel 13.30の新機能:chunkByによるデータ分割とStorageパスの安全性向上

30が公開された。Laravel Newsの速報によれば、Collectionに隣接要素を条件ごとに分割するchunkByが追加され、Storage::pathには他ファイルシステム系メソッドと同一のパス正規化が導入された。後者は既存コードが例外を投げる可能性があり、個人開発のプロジェクトでは影響範囲の把握が必須である。…

Laravel 13.30の新機能:chunkByによるデータ分割とStorageパスの安全性向上

Laravel 13.30が公開された。Laravel Newsの速報によれば、Collectionに隣接要素を条件ごとに分割するchunkByが追加され、Storage::pathには他ファイルシステム系メソッドと同一のパス正規化が導入された。後者は既存コードが例外を投げる可能性があり、個人開発のプロジェクトでは影響範囲の把握が必須である。

chunkBy — chunkWhileとの使い分け

chunkByはCollectionを「隣接する要素のうち、指定したキーまたはコールバックの戻り値が変化した地点」で分割する。引数にはキー文字列を渡す方法と、コールバックを渡す方法がある。キーにはドット記法(例:'address.city')が使える。内部でdata_getを通すためであり、各チャンク内の元キーは保持される。

既存のchunkWhileは「コールバックがfalseを返した箇所」で分割する設計である。Laravel Newsによれば、実務ではこのコールバック内で「現在要素」と「構築中チャンクの末尾要素」を比較するロジックを書く場面が多い。chunkByはその比較そのものをメソッド化したものである。

$collection = collect([
['user' => 1, 'role' => 'admin'],
['user' => 2, 'role' => 'admin'],
['user' => 3, 'role' => 'editor'],
]);
$chunks = $collection->chunkBy('role');

groupByは全要素をキーごとにまとめてから返す。chunkByは入力順を維持したまま隣接するブロックを返す点が異なる。時系列データや並び順に意味があるログ処理では、chunkByの方が意図に適合する。

Storage::pathの正規化 — 既存コードが例外を投げる

今回のリリースで最も注意すべき変更は、Storage::pathのセキュリティ強化である。

修正前、Storage::pathは引数の正規化を行わず、FlysystemのPathPrefixerに文字列をそのまま渡していた。PathPrefixerは単なる文字列連結処理であり、../を除去しない。結果として、ローカルディスクではstorage/app/../.envのような引数を渡すと、アプリケーションルートの.envへのネイティブパスを返していた。Storage::get、delete、readStreamは同じ引数を拒否しており、API間の挙動に不整合が生じていた。

13.30以降、Storage::pathは他メソッドと同じくWhitespacePathNormalizerを通す。../を含む相対パスはドライバの解決規則に従い、ディスクルート外へ解決される場合はPathTraversalDetected例外がスローされる。Laravel Newsによれば、pathが..セグメントを受け入れる前提のコードは例外を投げるようになる。

// 修正前:動作するが、.envへのパスが返る
$path = Storage::disk('local')->path($userInput);
// 修正後:../を含むと例外
// League\Flysystem\PathTraversalDetected

ユーザー入力や外部設定値をpathに渡しているコードは、要再確認である。

その他の改善とアップデートの優先順位

その他の変更点と、個人開発者にとっての優先度を整理する。

  • queue:workに--jsonフラグが追加された。ワーカー停止時にWorkerStopReasonが構造化ログとして出力される。WorkerStopReason enumにdescriptionが追加され、9種類の終了シナリオ(interrupted、lost connection、maximum jobs exceeded、memory limit exceeded、maximum run time exceeded、queue empty、queue empty for the configured duration、received restart signal、job timed out)が人間可読文字列として取得可能になった。--quietまたは--silent指定時は出力されない。
  • DevCommandsにonlyとexceptが追加された。コマンドの出自(framework / vendor / userland)によるフィルタリングが可能になった。いずれもオプトインであり、アプリケーション登録コマンドは対象外である。
  • データベースURL-parserが修正された。PDO_SQLSRVのネイティブ接続文字列をparse_urlがパスとして読み込み、先頭1文字が除去されてデータベース名がerver=127.0.0.1,1433になる不具合が解消された。

優先度の判断軸は次のとおり。

  • 即時確認が必要:Storage::pathにユーザー由来のパスを渡している箇所。例外発生リスクがある。
  • リファクタの候補:chunkWhile内で「現在要素と末尾要素の比較」だけを行っている箇所。chunkByで置換可能である。
  • 運用改善:queue:workの停止原因調査とDevCommandsの登録制御。本番環境でのみ意味を持つ。

関連記事: Laravel 11のContextクラス:リクエストを横断するデータ保持とログ出力の検証.

ニュースをもっと見る