Laravel 12・13の新機能まとめ|11→12→13へ実際にアップグレードしてみた
Laravel 12・13の新機能を整理しつつ、Laravel 11のプロジェクトを実際に作成して12→13へ順番にアップグレードし、詰まった点も含めて記録した検証記事です。
ざっくり Laravel 12・13へのアップグレード
Laravel 12 は破壊的変更をほぼ抑えた「メンテナンスリリース」、Laravel 13 は AI SDK や JSON:API 対応が入った機能追加リリースです。
どちらも公式のアップグレードガイド通りに 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 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上に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ビュー)もこの通り、いつも通りの見た目で表示できました。
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で検索してみましたが、そもそもどちらの名前も参照していなかったため、こちらもコード修正は不要でした。
気づいたこと・注意点
Composerのセキュリティアドバイザリブロックは、古いバージョンを意図的にインストールするときに引っかかる
今回のように「あえて古いバージョンから始めて、順にアップグレードする」ような検証・学習目的の作業では、composer config -g policy.advisories.block falseのような回避が必要になります。
逆に言うと、通常の新規プロジェクトでは知らないうちに脆弱なバージョンを掴まされにくくなっている、ということでもあるので、本番用途では無闇に無効化しない方がよさそうです。
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制約の追随も忘れずに進めてみてください。
最後まで読んでいただきありがとうございました。




