Documentation Index
Fetch the complete documentation index at: https://kawax.biz/llms.txt
Use this file to discover all available pages before exploring further.
Introduction
Laravel 13 was released in March 2026. This guide covers everything you need to upgrade a Laravel 12.x application to 13.x.Estimated upgrade time: about 10 minutes. The actual impact depends on the size of your application and which features you use.
AI-assisted upgrade
You can automate much of the upgrade process using Laravel Boost, the official MCP server for AI-assisted Laravel upgrades. Install it in your Laravel 12 application, then run the/upgrade-laravel-v13 slash command in Claude Code, Cursor, OpenCode, Gemini, or VS Code. Requires laravel/boost ^2.0.
If your AI tool does not support slash commands, you can achieve the same result by referencing the prompt file directly. Paste the following prompt into any AI assistant:
Prompt
Changes by impact level
High impact
- Updating dependencies
- Updating the Laravel installer
- Request forgery protection (CSRF)
Medium impact
- Cache
serializable_classesconfiguration - Session
serializationconfiguration
Low impact
- Cache prefix and session cookie name
- Collection model serialization
Container::calland nullable class defaults- Domain route registration priority
JobAttemptedevent exception payload- Manager
extendcallback binding - MySQL
DELETEqueries (JOIN / ORDER BY / LIMIT) - Pagination Bootstrap view names
- Polymorphic pivot table name generation
QueueBusyevent property renameStrfactory reset between tests
Upgrade steps
Updating dependencies
High impact Update the following entries in yourcomposer.json:
Updating the Laravel installer
High impact If you use the Laravel installer CLI to create new applications, update it to the version that supports Laravel 13.x. If you installed it withcomposer global require:
Breaking changes
Security
Request forgery protection
High impact The CSRF middleware has been renamed fromVerifyCsrfToken to PreventRequestForgery. It also adds origin validation using the Sec-Fetch-Site header.
VerifyCsrfToken and ValidateCsrfToken remain as deprecated aliases, but any direct references — especially in tests or route definitions that exclude the middleware — must be updated to PreventRequestForgery.
preventRequestForgery(...).
Cache
Cache prefix and session cookie name
Low impact The default cache and Redis key prefix now uses a hyphen-separated suffix, and the default session cookie name now usesStr::snake(...).
Most applications set these values explicitly in their config files and are not affected. Only applications that rely on the framework’s fallback defaults will see a difference.
.env:
Cache serializable_classes configuration
Medium impact
A serializable_classes option has been added to the default cache configuration, defaulting to false. This prevents PHP deserialization gadget-chain attacks if APP_KEY is ever leaked.
If your application intentionally stores PHP objects in the cache, you must explicitly list the classes that are allowed to be deserialized:
Session serialization configuration
Medium impact
The Laravel 13 skeleton (laravel/laravel) adds 'serialization' => 'json' to config/session.php. However, the framework’s internal default remains php.
The official upgrade guide does not mention changing this setting — the intent is that you do not need to change it.
To keep the same behavior as Laravel 12, set the value explicitly to php:
Container
Container::call and nullable class defaults
Low impact
Container::call now respects the default value of nullable class parameters when no binding exists — consistent with the behavior introduced for constructor injection in Laravel 12.
Database
MySQL DELETE queries
Low impact
Laravel now compiles full DELETE ... JOIN queries with ORDER BY and LIMIT clauses in MySQL grammar. Previously, those clauses were silently ignored in DELETE queries that included a JOIN.
In Laravel 13, these clauses are included in the generated SQL. This may cause a QueryException on database engines that do not support this syntax.
Eloquent
Polymorphic pivot table name generation
Low impact When a polymorphic pivot model class uses a custom pivot model, Laravel now generates a plural table name instead of a singular one. If your code relied on the singular inferred name, define the table name explicitly:Collection model serialization
Low impact When Eloquent model collections are serialized and restored (for example, in queued jobs), eager-loaded relationships are now restored along with the models. If any code depends on relationships being absent after deserialization, it will need to be updated.Queues
JobAttempted event exception payload
Low impact
The Illuminate\Queue\Events\JobAttempted event now exposes the exception object (or null) via $exception, replacing the old boolean $exceptionOccurred property.
QueueBusy event property rename
Low impact
The $connection property on Illuminate\Queue\Events\QueueBusy has been renamed to $connectionName to align with other queue events.
Routing
Domain route registration priority
Low impact Routes with an explicit domain now take precedence over non-domain routes during route matching. This ensures catch-all subdomain routes behave consistently, even when non-domain routes are registered first.Support
Manager extend callback binding
Low impact
Closures registered with a Manager’s extend method are now bound to the manager instance.
If you previously relied on a different object (such as a service provider instance) being available as $this inside these closures, move those values into use (...) captures:
Str factory reset between tests
Low impact
Laravel now resets custom Str factories during test teardown.
If you relied on a custom UUID, ULID, or random string factory persisting across test methods, set it up in each relevant test or in a setUp hook.
Views
Pagination Bootstrap view names
Low impact The internal pagination view names for Bootstrap 3 have been made explicit:Deprecated features
| Feature | Replacement |
|---|---|
VerifyCsrfToken middleware | PreventRequestForgery |
ValidateCsrfToken middleware | PreventRequestForgery |
JobAttempted::$exceptionOccurred | JobAttempted::$exception |
QueueBusy::$connection | QueueBusy::$connectionName |
New contract methods
Very low impact — only affects custom implementations of these contracts.Dispatcher contract
Illuminate\Contracts\Bus\Dispatcher now declares dispatchAfterResponse($command, $handler = null).
ResponseFactory contract
Illuminate\Contracts\Routing\ResponseFactory now declares the eventStream signature.
MustVerifyEmail contract
Illuminate\Contracts\Auth\MustVerifyEmail now declares markEmailAsUnverified().
Queue contract
Illuminate\Contracts\Queue\Queue now formally declares the following queue-size inspection methods (previously only in docblocks):
pendingSizedelayedSizereservedSizecreationTimeOfOldestPendingJob
Store / Repository contracts
The cache contracts now declare a touch method for TTL extension:
Common upgrade issues
CSRF-related tests fail
Symptom: Tests that referenceVerifyCsrfToken fail with a class-not-found error.
Fix: Replace all references with PreventRequestForgery.
Objects can’t be retrieved from the cache
Symptom: Cached data comes back asnull, or you see an UnserializationFailedException.
Fix: Add the classes to serializable_classes in config/cache.php, or convert your cached values to arrays.
JobAttempted listener stops working
Symptom: $event->exceptionOccurred is undefined or always null.
Fix: Switch to $event->exception !== null.
Users are logged out after upgrading
Symptom: All users are signed out immediately after the upgrade. Fix: The default session cookie name has changed. SetSESSION_COOKIE in your .env to preserve the previous value.
Cache miss rate spikes after upgrading
Symptom: Cache misses increase significantly right after the upgrade. Fix: The default cache prefix has changed. Either setCACHE_PREFIX in your .env or clear the cache.
References
- Official upgrade guide
- laravel/laravel diff (12.x → 13.x)
- Laravel Shift — automated upgrade service
- Laravel Boost — MCP server for AI-assisted upgrades