Introduction
Laravel 10 was released on February 14, 2023. This guide walks through the upgrade from Laravel 9.x to 10.x.Estimated time to upgrade is about 10 minutes. Actual impact from breaking changes depends on your app’s size and features you use.
Automated upgrades with Laravel Shift
You can automate the upgrade with Laravel Shift. Shift updates dependencies and configuration files automatically.Changes by impact level
Impact: high
- Dependency updates
minimum-stabilityupdate
Impact: medium
- Database expression changes
- Removal of the model
$datesproperty - Monolog 3
- Redis cache tags
- Service mocking changes
- The language directory
Impact: low
- Closure validation rule messages
- The
aftermethod on form requests - Public path binding
QueryExceptionconstructor- Rate limiter return value
- Removal of
Redirect::home - Removal of
Bus::dispatchNow - The
registerPoliciesmethod - ULID columns
Upgrade steps
Update dependencies
Impact: high Update the following dependencies incomposer.json.
Update minimum-stability
Impact: high
Update minimum-stability in composer.json to stable. Since stable is the default, you can also remove this setting altogether.
PHP version requirement
Impact: high Laravel 10 requires PHP 8.1.0 or later and Composer 2.2.0 or later.Breaking changes
Application
Public path binding
Impact: low If you customize the public path by bindingpath.public in the container, switch to Illuminate\Foundation\Application’s usePublicPath method.
Authorization
The registerPolicies method
Impact: low
The framework now calls AuthServiceProvider’s registerPolicies method automatically. You can remove the manual call from boot.
Cache
Redis cache tags
Impact: mediumCache::tags() is recommended only for apps using Memcached. If you use Redis as your cache driver, consider migrating to Memcached.
Database
Database expression changes
Impact: medium Database expressions produced byDB::raw have been rewritten. To get the raw string value of an expression, use the getValue(Grammar $grammar) method. Casting to (string) no longer works.
QueryException constructor
Impact: very low
The Illuminate\Database\QueryException constructor now takes a connection name string as the first argument. If you manually throw this exception, adjust the code.
ULID columns
Impact: low When you call theulid method in a migration without arguments, the column name is now ulid. In previous releases, calling it without arguments incorrectly created a column named uuid.
Eloquent
The model $dates property
Impact: medium
The deprecated $dates property on Eloquent models has been removed. Use the $casts property instead.
Localization
The language directory
Impact: none Existing apps aren’t affected, but new Laravel application skeletons no longer include thelang directory by default. Publish it via an Artisan command if needed.
Logging
Monolog 3
Impact: medium Laravel’s Monolog dependency has been updated to Monolog 3.x. If you use Monolog directly in your app, review the Monolog upgrade guide. If you use third-party logging services like BugSnag or Rollbar, you may need to upgrade to versions that support both Monolog 3.x and Laravel 10.x.Queue
Removal of Bus::dispatchNow
Impact: low
The deprecated Bus::dispatchNow and dispatch_now methods have been removed. Use Bus::dispatchSync and dispatch_sync.
Routing
Middleware aliases
Impact: optional In new Laravel apps,App\Http\Kernel’s $routeMiddleware property was renamed to $middlewareAliases. Applying it to existing apps is optional.
Rate limiter return value
Impact: low When you callRateLimiter::attempt, the return value of the provided closure is now returned as-is. If you return nothing or null, true is returned.
Removal of Redirect::home
Impact: very low
The deprecated Redirect::home method has been removed. Redirect to a named route explicitly.
Testing
Service mocking
Impact: medium The deprecatedMocksApplicationServices trait has been removed from the framework. It provided test methods like expectsEvents, expectsJobs, and expectsNotifications.
If you use these methods, migrate to Event::fake, Bus::fake, and Notification::fake respectively.
Validation
Closure validation rule messages
Impact: very low In closure-based custom validation rules, calling$fail multiple times now appends messages to an array instead of overwriting.
Also, the $fail callback now returns an object. If you type-hint the return value of a validation closure, update it.
The after method on form requests
Impact: very low
Laravel now reserves an after method on form requests. If your form request defines an after method, rename it or migrate to the new “after validation” feature.
Summary
Laravel 10 involves relatively small changes, and the upgrade can be completed quickly.References
- Official upgrade guide (English)
- laravel/laravel diff (9.x → 10.x)
- Laravel Shift — community service to automate upgrades
- Sanctum upgrade guide (2.x → 3.x)
- Monolog 3.x upgrade guide