Skip to main content

Introduction

Laravel 12 was released in February 2025. This guide walks through upgrading from Laravel 11.x to 12.x.
Estimated time to upgrade is about 5 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 using Laravel Shift. Shift updates dependencies and configuration files automatically.

Changes by impact level

Impact: high

  • Dependency updates
  • Laravel installer update

Impact: medium

  • Eloquent HasUuids trait and UUIDv7

Impact: low

  • Carbon 3
  • Concurrency result index mapping
  • Container class dependency resolution
  • SVG exclusion from image validation
  • Default root path for the local filesystem disk
  • Multi-schema database inspection
  • Merging nested array requests

Upgrade steps

Update dependencies

Impact: high Update the following dependencies in composer.json.
Then install dependencies:

Update the Laravel installer

Impact: high If you use the Laravel installer CLI to create new Laravel apps, update it to the version that supports Laravel 12.x and the new starter kits. If installed via composer global require:
If installed via php.new, run the reinstall command for your OS.
If you use the Laravel Herd bundled version, update Herd itself to its latest release.

New starter kits

Laravel 12 introduces new starter kits to replace the previous Breeze and Jetstream. Running laravel new lets you interactively pick a frontend stack. Available starter kits:
  • React — Inertia 2, React 19, TypeScript, Tailwind 4, shadcn/ui
  • Vue — Inertia 2, Vue Composition API, TypeScript, Tailwind 4, shadcn-vue
  • Svelte — Inertia 2, Svelte 5, TypeScript, Tailwind 4, shadcn-svelte
  • Livewire — Livewire, Tailwind 4, Flux UI
Running the command prompts you to choose a starter kit. After choosing, install dependencies and start the dev server.
When upgrading existing apps, you don’t need to reinstall a starter kit. It’s a change for new projects.

Breaking changes

Eloquent

HasUuids trait and UUIDv7

Impact: medium The HasUuids trait now returns UUID v7 (ordered UUIDs). To keep the previous ordered UUID v4 behavior, switch to the HasVersion4Uuids trait.
If you previously used the HasVersion7Uuids trait, switch to HasUuids (which now has the same behavior).

Validation

SVG exclusion from image validation

Impact: low The image validation rule no longer allows SVG by default. To allow SVG, specify it explicitly.

Storage

Default root path for the local filesystem disk

Impact: low If the local disk isn’t explicitly defined in the filesystems configuration, its default root path has changed from storage/app to storage/app/private. To keep the previous behavior, define the local disk explicitly in the configuration file.

Database

Multi-schema database inspection

Impact: low Schema::getTables(), Schema::getViews(), and Schema::getTypes() now return results from all schemas by default. To target only a specific schema, pass the schema argument.
Schema::getTableListing() now returns schema-qualified table names by default.

Database constructor signature change

Impact: very low Illuminate\Database\Schema\Blueprint and Illuminate\Database\Grammar constructors now require a Connection instance as their first argument.
The following APIs are also deprecated or removed. Get the table prefix directly from the connection.

Concurrency

Result index mapping

Impact: low When you pass an associative array to Concurrency::run(), results are now returned associated with their keys.

Container

Default values in class dependency resolution

Impact: low The DI container now respects default class property values when resolving class instances.

Requests

Merging nested array requests

Impact: low $request->mergeIfMissing() can now merge nested array data using dot notation. Previously, dot-notation keys were created as top-level keys as-is.

Routing

Route priority

Impact: low The behavior when multiple routes have the same name is now consistent between cached and uncached routing. Even without caching, the first-registered route now wins instead of the last.

Authentication

DatabaseTokenRepository constructor change

Impact: very low The Illuminate\Auth\Passwords\DatabaseTokenRepository constructor’s $expires parameter now takes seconds rather than minutes.

Carbon 3

Impact: low Carbon 2.x support has been dropped. All Laravel 12 apps require Carbon 3.x.

Summary

Laravel 12 is a comparatively smooth upgrade. Here are the main things to watch out for.

References

Last modified on July 13, 2026