Laravel 12・13の新機能まとめ|11→12→13へ実際にアップグレードしてみた
Laravel 12・13の新機能を整理しつつ、Laravel 11のプロジェクトを実際に作成して12→13へ順番にアップグレードし、詰まった点も含めて記録した検証記事です。
Laravel 13 がリリースされていたので、公式のアップグレードガイドを読みながら、Laravel 11 のプロジェクトを実際に作って 12→13 の順にアップグレードしてみました。
結論から言うと、どちらも公式ガイド通りに composer.json を書き換えて composer update するだけで、今回のようなシンプルな構成であればコード修正は不要でした。
ただし実際にやってみると、ドキュメントには載っていない詰まりどころもいくつかあったので、そのまま記録しておきます。
Laravel 12・13 の新機能
Laravel 12(2025 年 2 月リリース)
公式ドキュメントによると、Laravel 12 は既存アプリへの影響を最小限に抑えることを重視した、比較的マイナーなリリースとのことです。
- 新しいアプリケーションスターターキット:React・Svelte・Vue・Livewire 向けが刷 新され、Inertia 2・TypeScript・shadcn/ui・Tailwind を採用(Livewire キットは Flux UI・Laravel Volt)
- WorkOS AuthKit 搭載オプション:ソーシャル認証・パスキー・SSO に対応したスターターキットも選べるようになった
- UUID のデフォルトが v7 に変更:
HasUuidsトレイトが順序付き UUID(v7)を生成するようになった。従来の v4 を維持したい場合はHasVersion4Uuidsに置き換えが必要 - SVG 画像バリデーションがデフォルトで非許可に:許可する場合は
image:allow_svgルールを明示する必要がある - ローカルディスクのデフォルトが
storage/app/privateに変更 - PHP 8.2〜8.5 に対応(バグフィックスは 2025 年 8 月まで、セキュリティ修正は 2027 年 2 月まで)
Laravel 13(2026 年リリース)
公式ドキュメントによると、Laravel 13 は以下のような機能が追加されたリリースとのことです。
- ファーストパーティの Laravel AI SDK:テキスト・画像・音声生成や埋め込みを、プロバイダに依存しない統一 API で扱えるようになった
- JSON:API レスポンスの標準対応:JSON:API 仕様に準拠したリソースレスポンスを簡潔に実装できる
- CSRF 保護ミドルウェアの改名:
VerifyCsrfTokenがPreventRequestForgeryに変わり、オリジン認識のリクエスト検証が追加された Queue::route(...):ジョブクラスごとにキュー・接続先を 1 箇所で定義できるよう になった#[Middleware]・#[Authorize]・#[Tries]・#[Backoff]などの PHP 属性:ルーティングやキューの設定を、より宣言的に書けるようになったCache::touch(...):キャッシュの値は変えずに TTL だけ延長できる- PostgreSQL + pgvector を使ったセマンティック検索に対応
- PHP の最小要件が 8.3 に引き上げ(Laravel 12 は PHP 8.2〜)
Docker 上で Laravel 11 を作り、12→13 へ実際にアップグレードした
公式ガイドを読むだけでなく、Docker 上に PHP 8.3 の環境を作り、実際に Laravel 11 のプロジェクトを作成した上で、12→13 の順に本当にアップグレードしてみました。
1. Laravel 11 のプロジェクトを作成
composer create-project "laravel/laravel:^11.0" laravel-upgrade-guide-demoこれを実行したところ、いきなりエラーで止まりました。
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Root composer.json requires laravel/framework ^11.31, found laravel/framework[v11.31.0, ..., v11.56.1]
but these were not loaded, because they are affected by security advisories
("PKSA-m5cs-t1y6-qpcs", "PKSA-3r5d-mb8f-1qw9", "PKSA-mdq4-51ck-6kdq", ...).Composer 2.10 系から入った、既知のセキュリティアドバイザリが出ているバージョンのインストールをデフォルトでブロックする機能に引っかかったようです。
composer auditで詳細を見ると、laravel/frameworkに対して以下 3 件のアドバイザリが出ていました(Laravel 11.56.1 時点)。
| Advisory ID | Severity | 内容 |
|---|---|---|
| PKSA-m5cs-t1y6-qpcs | medium | 署名付き一時 URL のパス混同 |
| PKSA-3r5d-mb8f-1qw9 | high | デフォルトの email バリデーションルールでの CRLF インジェクション |
| PKSA-mdq4-51ck-6kdq(CVE-2026-48019) | - | 同上(CVE 採番版) |
今回はあくまで「11 から順にアップグレードする過程」を検証したいので、アドバイザリの是非は判断せず、以下でこのブロックだけ一時的に無効化しました。
composer config -g policy.advisories.block falseこれで無事に Laravel 11.56.1 がインストールできました。
php artisan --version
# Laravel Framework 11.56.1トップページ(Welcome ビュー)もこの通り、いつも通りの見た目で表示できまし た。
セキュリティアドバイザリのブロックは、古いバージョンを意図的にインストールするときに引っかかる
今回のように「あえて古いバージョンから始めて、順にアップグレードする」ような検証・学習目的の作業では、composer config -g policy.advisories.block falseのような回避が必要になることが分かりました。
逆に言うと、通常の新規プロジェクトでは知らないうちに脆弱なバージョンを掴まされにくくなっている、ということでもあるので、本番用途では無闇に無効化しない方がよさそうです。
2. Laravel 11 → 12 へアップグレード
公式のアップグレードガイドに沿って、composer.jsonのrequireを書き換えます。
- "laravel/framework": "^11.31",
+ "laravel/framework": "^12.0",composer update --with-all-dependenciesLock file operations: 1 install, 1 update, 0 removals
- Upgrading laravel/framework (v11.56.1 => v12.68.0)
- Locking symfony/polyfill-php84 (v1.38.1)
...
No security vulnerability advisories found.laravel/frameworkのバージョンが上がっただけで、依存パッケージの追加はsymfony/polyfill-php84が増えた程度でした。
さきほどの 3 件のセキュリティアドバイザリも、12.68.0 では解消済みで「No security vulnerability advisories found.」に変わっています。
php artisan --version
# Laravel Framework 12.68.0
php artisan test
# PASS Tests\Unit\ExampleTest
# PASS Tests\Feature\ExampleTest
# Tests: 2 passed (2 assertions)今回はまっさらな状態のプロジェクトだったため、HasUuidsトレイトもVerifyCsrfTokenへの直接参照も存在せず、コードの修正は一切不要でした。
トップページの見た目も変化はありません(デフォルトの Blade テンプレート自体はバージョン間で変わっていないため、画像は割愛します)。
3. Laravel 12 → 13 へアップグレード
続けて 13 へのアップグレードです。公式ガイドの指示通り、laravel/frameworkに加えてlaravel/tinker・phpunit/phpunitも上げます。
"require": {
- "php": "^8.2",
- "laravel/framework": "^12.0",
- "laravel/tinker": "^2.9"
+ "php": "^8.3",
+ "laravel/framework": "^13.0",
+ "laravel/tinker": "^3.0"
},
"require-dev": {
...
- "phpunit/phpunit": "^11.0.1"
+ "phpunit/phpunit": "^12.0"
},composer update --with-all-dependencies今度は依存の連鎖が広く、guzzlehttp/guzzle(7.15.5→8.1.0)やphpunit/phpunit(11.5.56→12.5.34)まで芋づる式に上がりました。
- Upgrading laravel/framework (v12.68.0 => v13.29.0): Extracting archive
- Upgrading laravel/tinker (v2.11.1 => v3.0.2): Extracting archive
- Upgrading guzzlehttp/guzzle (7.15.5 => 8.1.0): Extracting archive
- Upgrading phpunit/phpunit (11.5.56 => 12.5.34): Extracting archive
...
No security vulnerability advisories found.php artisan --version
# Laravel Framework 13.29.0
php artisan test
# PASS Tests\Unit\ExampleTest
# PASS Tests\Feature\ExampleTest
# Tests: 2 passed (2 assertions)app/・bootstrap/・routes/配下をVerifyCsrfToken・PreventRequestForgeryで検索してみましたが、そもそもどちらの名前も参照していなかったため、こちらもコード修正は不要でした。
php制約は自動では上がらない
Laravel 13(正確にはlaravel/framework 13 系)のcomposer.jsonを見ると、"php": "^8.3"が要求されています。
grep -A1 '"require"' vendor/laravel/framework/composer.json
# "require": {
# "php": "^8.3",ですが、自分のプロジェクトのcomposer.jsonにある"php": "^8.2"という制約は、composer updateしても自動では書き換わりませんでした。
今回の検証環境は PHP 8.3 が入っていたので実害はありませんでしたが、放置すると PHP 8.2 環境でこのプロジェクトを新規セットアップしようとしたときに、依存解決の段階でエラーになります(実際の PHP バージョンではなく、composer.json側の宣言だけがズレる形)。
アップグレードガイドを一通りこなした後は、アップグレード対象パッケージ自身のvendor/.../composer.jsonを覗いて、php制約も手動で追随させておくのが安全そうです。
まっさらなプロジェクトなら、11→12→13 は本当にノーコードで通った
今回の構成(Blade のみ、フロントのスターターキットなし、UUID や CSRF ミドルウェアのカスタマイズなし)では、composer.jsonの書き換えとcomposer updateだけで 2 段階のメジャーアップグレードが完了しました。
とはいえこれは「変更点に該当するコードを元々書いていなかった」だけの話で、実運用中のアプリでは、UUID 生成・SVG アップロード・CSRF 周りのカスタマイズ・キャッシュのシリアライズ設定などを使っていないか、アップグレードガイドの一覧と照らし合わせておいた方がよさそうです。
まとめ
Laravel 12 は「変更を抑えたメンテナンスリリース」、Laravel 13 は「AI SDK や JSON:API 対応が入った機能追加リリース」という位置づけの違いが、実際にアップグレードしてみてもそのまま体感できました。
composer.jsonの書き換え自体は公式ガイド通りで数分の作業でしたが、Composer のセキュリティアドバイザリブロックのような、ドキュメントに載っていない挙動に実際に当たれたのは、手を動かしてみたからこその収穫でした。
これか ら 11・12 から上げようとしている方は、composer auditで現状のアドバイザリを確認しつつ、php制約の追随も忘れずに進めてみてください。
最後まで読んでいただきありがとうございました。




