Eindeutige Werte (Unique Values) sind in vielen Anwendungen wichtig, etwa um doppelte Benutzernamen oder E-Mail-Adressen zu verhindern. Im Laravel-Eloquent-Kontext bedeutet das: Wir wollen sicherstellen, dass bestimmte Felder pro Datenbank nicht doppelt vorkommen. Laravel bietet dafür auf zwei Ebenen Unterstützung – Datenbank-Level (Unique-Constraints) und Applikations-Level (Validierung). In Laravel 12 hat sich an den Grundlagen wenig geändert, aber es gab kleinere Verbesserungen und neue Tools. In diesem Beitrag schauen wir uns an, wie Eloquent-Modelle mit dem unique-Thema umgehen, welche Möglichkeiten es gibt, Unterschiede zu früheren Laravel-Versionen und Best Practices, um Fehler bei Unique-Prüfungen zu vermeiden.
Unique-Constraints in der Datenbank (Datenbankebene)
Die zuverlässigste Methode, eindeutige Werte sicherzustellen, ist ein Unique-Index in der Datenbank. Dies wird in Laravel meist per Migration definiert. Beispielsweise können wir in einer Migration einen Unique-Index für die Spalte email setzen:Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('email')->unique();
// ... weitere Spalten ...
});
$table->unique(['team_id', 'name']);
Dieses Migration-Snippet würde sicherstellen, dass die Kombination aus team_id und name einzigartig ist (kein doppelter Name pro Team).
Solche Datenbank-Constraints sorgen dafür, dass die Datenintegrität garantiert ist – die Datenbank selbst verweigert doppelte Einträge.
Wie reagiert Eloquent darauf?
Wenn wir versuchen, ein Eloquent-Modell mit einem bereits vorhandenen eindeutigen Wert zu speichern, wirft die Datenbank einen Fehler (meist ein SQL Integrity Constraint Violation). Laravel fängt dies als Exception vom Typ Illuminate\Database\QueryException ab. Ohne spezielle Behandlung bricht der Request dann mit einer Fehlermeldung ab. In Laravel 12 gibt es sogar eine neue Hilfsmethode getRawSql() am QueryException, um das fehlerhafte SQL leichter zu debuggen. In der Praxis sollte man solche Exceptions abfangen und dem Nutzer eine verständliche Fehlermeldung geben (oder – besser – das Duplikat schon vorher per Validierung verhindern, dazu gleich mehr).Unique Null Values (PostgreSQL Besonderheit):
In SQL-Datenbanken werden NULL-Werte in Unique-Indices normalerweise als verschieden behandelt – d.h. mehrere NULL sind erlaubt. PostgreSQL 15 hat jedoch die Möglichkeit eingeführt, NULL als gleichen Wert zu betrachten (UNIQUE NULLS NOT DISTINCT). Laravel 12 hat Support dafür hinzugefügt: Man kann nun bei PostgreSQL-Indices angeben, dass NULL-Werte als nicht unterscheidbar gelten sollen. Dafür gibt es eine Fluent-Methode nullsNotDistinct() in Laravel 12, die man an den Unique-Index hängen kann. Beispiel:
// Nur PostgreSQL:
$table->unique('token')->nullsNotDistinct();
Fazit Datenbankebene:
Ein Unique-Constraint auf der Datenbankseite ist unverzichtbar, um Datenbank-Duplikate definitiv auszuschließen. Allerdings bekommt der Benutzer einen rohen Fehler, wenn man sich allein darauf verlässt. Daher kombiniert man diese Strategie fast immer mit einer Überprüfung auf Applikationsebene.Unique-Validierung auf Applikationsebene (Eloquent Validierung)
Laravel bietet eine eingebaute Validierungsregel namens unique: für Formulare und Daten, um Duplikate vor dem Speichern abzufangen. Diese Regel prüft, ob ein gegebener Wert schon in einer bestimmten Datenbanktabelle existiert, und schlägt fehl, wenn ja. Typischerweise nutzt man die Regel in Form Requests oder im Controller, z. B.:$request->validate([
'email' => 'required|email|unique:users,email',
'username' => 'required|unique:users,username',
]);
Unique-Regel beim Aktualisieren (eigene ID ignorieren)
Eine Besonderheit bei Updates: Wenn ein Benutzer z.B. seine E-Mail im Profil nicht ändert, würde die obige Regel unique:users,email fälschlicherweise anschlagen – die E-Mail „existiert bereits“ (nämlich beim gleichen Datensatz). Wir müssen also der Validierung sagen, dass sie den aktuellen Datensatz ignorieren soll. Laravel ermöglicht das mit einem dritten Parameter in der Rule-Definition oder eleganter mit der Rule-Klasse.Variante 1:
per Regel-String den Datensatz ausschließen. Das Format lautet: unique:table,column,ignoreValue,idColumn. Beispiel:// In einem FormRequest für User-Update:
'email' => 'required|email|unique:users,email,'.$user->id,
Variante 2 (empfohlen):
Fluent-Definition mit Illuminate\Validation\Rule. Beispiel:use Illuminate\Validation\Rule;
'email' => [
'required', 'email',
Rule::unique('users', 'email')->ignore($user->id)
],
Unique-Regel mit zusätzlichen Bedingungen (Scopes)
Manchmal soll ein Wert innerhalb einer Gruppe einzigartig sein. Beispiel: Der Feldname code soll pro company_id nur einmal vorkommen (Kombination eindeutig). Hierfür bietet Laravel die Möglichkeit, zusätzliche Bedingungen (WHERE-Klauseln) an die Unique-Prüfung zu hängen. Mit der Rule-Klasse kann man ->where(...) nutzen, um z.B. einen bestimmten Firmen-Kontext einzuschränken:use Illuminate\Validation\Rule;
'code' => [
'required',
Rule::unique('products', 'code')->where(fn ($query) =>
$query->where('company_id', $request->company_id)
)
],
Kommentare 0
Noch keine Kommentare. Seien Sie der Erste!