Zum Hauptinhalt springen

Einleitung

Laravel 12 wurde im Februar 2025 veröffentlicht. Dieser Leitfaden beschreibt die Upgrade-Schritte von Laravel 11.x auf 12.x.
Der geschätzte Zeitaufwand liegt bei etwa 5 Minuten. Die tatsächliche Auswirkung der Breaking Changes hängt jedoch vom Umfang und den genutzten Funktionen ab.

Automatisches Upgrade mit Laravel Shift

Sie können das Upgrade auch mit Laravel Shift automatisieren. Shift aktualisiert Abhängigkeiten und Konfigurationsdateien der Anwendung automatisch.

Änderungen nach Auswirkung

Auswirkung: Hoch

  • Aktualisierung der Abhängigkeiten
  • Aktualisierung des Laravel-Installers

Auswirkung: Mittel

  • Eloquent-Trait HasUuids und UUIDv7

Auswirkung: Niedrig

  • Carbon 3
  • Index-Mapping der Ergebnisse in Concurrency
  • Klassenabhängigkeits-Auflösung im Container
  • SVG-Ausschluss bei der Image-Validierung
  • Default-Root-Pfad des lokalen Filesystem-Disks
  • Datenbank-Inspektion über mehrere Schemata
  • Merge verschachtelter Array-Requests

Upgrade-Schritte

Abhängigkeiten aktualisieren

Auswirkung: Hoch Aktualisieren Sie in composer.json folgende Abhängigkeiten.
{
  "require": {
    "laravel/framework": "^12.0"
  },
  "require-dev": {
    "phpunit/phpunit": "^11.0",
    "pestphp/pest": "^3.0"
  }
}
Installieren Sie anschließend die Abhängigkeiten:
composer update

Laravel-Installer aktualisieren

Auswirkung: Hoch Wenn Sie neue Laravel-Anwendungen mit dem Laravel-Installer-CLI erstellen, aktualisieren Sie diesen auf eine Version, die Laravel 12.x und die neuen Starterkits unterstützt. Wenn per composer global require installiert:
composer global update laravel/installer
Bei Installation über php.new verwenden Sie den passenden Reinstallationsbefehl für Ihr Betriebssystem.
/bin/bash -c "$(curl -fsSL https://php.new/install/mac/8.4)"
Wenn Sie die Bundled-Version von Laravel Herd verwenden, aktualisieren Sie Herd auf die neueste Version.

Neue Starterkits

In Laravel 12 wurden neue Starterkits eingeführt, die die bisherigen Breeze und Jetstream ablösen. Beim Ausführen von laravel new wählen Sie den Frontend-Stack interaktiv aus. Verfügbare Starterkits:
  • 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
laravel new my-app
Beim Ausführen wählen Sie das gewünschte Starterkit aus. Anschließend genügt das Installieren der Abhängigkeiten und der Start des Entwicklungsservers.
cd my-app
npm install && npm run build
composer run dev
Beim Upgrade bestehender Anwendungen muss ein Starterkit nicht neu eingeführt werden. Die Neuerungen gelten für neue Projekte.

Breaking Changes

Eloquent

Trait HasUuids und UUIDv7

Auswirkung: Mittel Das Trait HasUuids liefert nun UUID v7 (geordnete UUIDs). Möchten Sie das bisherige Verhalten mit geordneten UUID v4 beibehalten, wechseln Sie auf das Trait HasVersion4Uuids.
use Illuminate\Database\Eloquent\Concerns\HasUuids; // [tl! remove]
use Illuminate\Database\Eloquent\Concerns\HasVersion4Uuids as HasUuids; // [tl! add]
Falls Sie bislang das Trait HasVersion7Uuids verwendet haben, wechseln Sie auf HasUuids (Verhalten ist nun identisch).

Validierung

SVG-Ausschluss bei der Image-Validierung

Auswirkung: Niedrig Die Rule image erlaubt standardmäßig keine SVGs mehr. Wenn Sie SVGs erlauben möchten, geben Sie das explizit an.
use Illuminate\Validation\Rules\File;

'photo' => 'required|image:allow_svg'

// oder
'photo' => ['required', File::image(allowSvg: true)],

Storage

Default-Root-Pfad des lokalen Filesystem-Disks

Auswirkung: Niedrig Wenn Sie in filesystems keinen local-Disk explizit definiert haben, wurde der Default-Root von storage/app auf storage/app/private geändert. Um das bisherige Verhalten beizubehalten, definieren Sie den local-Disk explizit.
// config/filesystems.php
'local' => [
    'driver' => 'local',
    'root' => storage_path('app'),
],

Datenbank

Datenbank-Inspektion über mehrere Schemata

Auswirkung: Niedrig Schema::getTables(), Schema::getViews() und Schema::getTypes() geben standardmäßig Ergebnisse aus allen Schemata zurück. Zur Einschränkung auf ein Schema übergeben Sie das Argument schema.
// Tabellen aus allen Schemata
$tables = Schema::getTables();

// Nur Tabellen aus dem Schema 'main'
$tables = Schema::getTables(schema: 'main');
Schema::getTableListing() liefert standardmäßig schema-qualifizierte Tabellennamen.
$tables = Schema::getTableListing();
// ['main.migrations', 'main.users', 'blog.posts']

$tables = Schema::getTableListing(schema: 'main', schemaQualified: false);
// ['migrations', 'users']

Änderungen an Datenbank-Konstruktorsignaturen

Auswirkung: Sehr niedrig Die Konstruktoren von Illuminate\Database\Schema\Blueprint und Illuminate\Database\Grammar erwarten nun als erstes Argument eine Connection-Instanz.
// Laravel <= 11.x
$grammar = new MySqlGrammar;
$grammar->setConnection($connection);

// Laravel >= 12.x
$grammar = new MySqlGrammar($connection);
Zudem wurden folgende APIs entfernt oder als deprecated markiert.
APIStatus
Blueprint::getPrefix()deprecated
Connection::withTablePrefix()entfernt
Grammar::getTablePrefix() / setTablePrefix()deprecated
Grammar::setConnection()entfernt
Den Tabellenpräfix beziehen Sie direkt aus der Connection.
$prefix = $connection->getTablePrefix();

Concurrency

Index-Mapping der Ergebnisse

Auswirkung: Niedrig Wenn Sie Concurrency::run() ein assoziatives Array übergeben, werden die Ergebnisse jetzt den jeweiligen Keys zugeordnet zurückgegeben.
$result = Concurrency::run([
    'task-1' => fn () => 1 + 1,
    'task-2' => fn () => 2 + 2,
]);

// ['task-1' => 2, 'task-2' => 4]

Container

Default-Werte bei der Auflösung von Klassenabhängigkeiten

Auswirkung: Niedrig Der DI-Container berücksichtigt beim Auflösen von Klassen-Instanzen die Default-Werte von Klassen-Properties.
class Example
{
    public function __construct(public ?Carbon $date = null) {}
}

$example = resolve(Example::class);

// Laravel <= 11.x: liefert eine Carbon-Instanz
// Laravel >= 12.x: liefert null

Requests

Merge verschachtelter Array-Requests

Auswirkung: Niedrig $request->mergeIfMissing() unterstützt jetzt das Mergen verschachtelter Array-Daten in Dot-Notation. Bisher wurden Dot-Notation-Keys als Top-Level-Keys angelegt.
$request->mergeIfMissing([
    'user.last_name' => 'Otwell',
]);

Routing

Priorität von Routen

Auswirkung: Niedrig Bei mehreren Routen mit gleichem Namen wurde das Verhalten mit und ohne Cache vereinheitlicht. Auch ohne Route-Cache hat nun die zuerst registrierte Route Vorrang, nicht die zuletzt registrierte.

Authentifizierung

Änderung des DatabaseTokenRepository-Konstruktors

Auswirkung: Sehr niedrig Der Konstruktor von Illuminate\Auth\Passwords\DatabaseTokenRepository erwartet den Parameter $expires nun in Sekunden, nicht mehr in Minuten.

Carbon 3

Auswirkung: Niedrig Der Support für Carbon 2.x wurde entfernt. Laravel-12-Anwendungen benötigen Carbon 3.x.

Fazit

Laravel 12 lässt sich vergleichsweise reibungslos aktualisieren. Zusammenfassung der wichtigsten Punkte:
ÄnderungAuswirkungMaßnahme
Abhängigkeiten in composer.json aktualisierenHochAuf laravel/framework ^12.0 heben
Laravel-Installer aktualisierenHochcomposer global update
HasUuids → UUIDv7MittelBei Bedarf auf HasVersion4Uuids wechseln
SVG-Ausschluss bei image-ValidierungNiedrigallow_svg ergänzen, wenn SVGs erlaubt sein sollen
Änderung des Default-Root-Pfads für lokalen DiskNiedrigKonfiguration explizit angeben
Carbon 3 erforderlichNiedrigAPI-Kompatibilität prüfen

Referenzen

Zuletzt geändert am 13. Juli 2026