
Was ist das Eloquent ORM?
Das Eloquent ORM kommt zusammen mit dem Laravel-Framework und bietet einen einfachen, unkomplizierten Weg, mit einer Datenbank zu arbeiten. Bekannt geworden ist es unter anderem für Soft Deletes, Timestamps, die Umsetzung des Active-Record-Musters, den Umgang mit mehreren Datenbanken, Eager Loading, Model-Observer und Model-Events. Eloquent-Beziehungen sind schlicht Methoden der Eloquent-Model-Klassen. Als Methoden definiert, sind Beziehungen mächtige Query-Builder: Du kannst Methoden verketten und daraus sehr ausdrucksstarke Abfragen bauen.
Wie funktioniert das Eloquent ORM?
Eloquent ist für seine Umsetzung des Active-Record-Musters bekannt. Active Record ist ein Architekturmuster, bei dem jedes Model der MVC-Architektur einer Tabelle in der Datenbank entspricht. Damit legst du Beziehungen in deiner Datenbank an und arbeitest objektorientiert mit ihnen. SQL-Abfragen von Hand zu schreiben ist mühsam und kostet viel Zeit. Laravel Eloquent nimmt dir die gängigen Datenbankoperationen ohne lange SQL-Statements ab. Einfügen, Aktualisieren, Löschen und das Abgleichen mehrerer Datenbanken werden über die Models sehr einfach. Du definierst nur die Tabellen und ihre Beziehungen, den Rest erledigt Eloquent.
Erste Schritte mit Eloquent
Laravel bringt eine eigene Kommandozeile mit, die Artisan Console. Sie baut auf der Console-Komponente von Symfony auf und macht die Kommandozeile während der Entwicklung leicht nutzbar.
Bevor wir weitergehen, richte die Datenbankverbindung in der Datei config/database.php ein.
Und bevor du mit einem Eloquent-Model arbeitest, prüfe, ob Laravel installiert ist. Falls nicht, lädst du es über getcomposer.org
Die Liste der verfügbaren Artisan-Befehle bekommst du so:
php artisan listDanach erscheinen alle Befehle mit einer kurzen Beschreibung auf dem Bildschirm. Brauchst du Hilfe zu einem bestimmten Befehl, stellst du ihm einfach „help“ voran. Beispiel:
php artisan help migrateEloquent-Models anlegen
Als Erstes brauchst du ein Model für die Datenbank. Models helfen dir beim Seeding, bei Migrationen und mehr. Es ist das Model, das mit der Datenbank spricht: Über das Model fragst du sie ab und befüllst sie mit Daten. Üblicherweise liegt es unter App\Models – allein der Übersichtlichkeit halber. Wir halten uns ebenfalls daran, du musst es aber nicht, die einzige Bedingung ist, dass die Klasse laut deiner composer.json automatisch geladen wird. Jedes Eloquent-Model erbt von der Klasse Illuminate\Database\Eloquent\Model. Der Grundbefehl zum Anlegen ist der Artisan-Befehl `make:model`:
php artisan make: model StudentDie Grundstruktur eines Models sieht so aus:
class User extends Model {}Die Migration lässt sich gleich beim Anlegen des Models erzeugen, indem du `-m` oder `-migration` an den vorigen Befehl hängst.
php artisan make:model Student--migration
php artisan make:model Flight -mSeeder, Factories, Controller und weitere Klassen erzeugst du, indem du dem Artisan-Befehl `make:model` die passenden Optionen mitgibst. Beispiele:
php artisan make:model Flight --factory
php artisan make:model Flight -f
php artisan make:model Flight --seed
php artisan make:model Flight -s
php artisan make:model Flight --controller
php artisan make:model Flight -cDiese Optionen lassen sich außerdem kombinieren, um mehrere Klassen auf einmal anzulegen.
php artisan make:model Flight -mfscEin paar Konventionen solltest du dabei im Kopf behalten:
- Tabellenname: Konventionsgemäß ist der Tabellenname die kleingeschriebene Pluralform des Model-Namens. Heißt das Model Student, lautet die Tabelle students. Besteht der Model-Name aus mehreren Wörtern, trennst du sie mit Unterstrichen.
- Primärschlüssel: Eloquent geht von einer Spalte id als Primärschlüssel aus. Überschreiben kannst du das mit `$primaryKey`.
- Timestamps: Standardmäßig pflegt Eloquent `created_at` und `updated_at` automatisch. Willst du das nicht, setzt du `$timestamp` auf false. Für ein eigenes Datumsformat nimmst du die Eigenschaft `$dateFormat` in deinem Model.
Datensätze aktualisieren und löschen
Aktualisieren
Um ein Model zu aktualisieren, holst du es, änderst das gewünschte Attribut und rufst save() auf. Die Spalte `updated_at` wird dabei automatisch gesetzt, du musst dich also nicht selbst darum kümmern.
$student = Student::find(1);
$student->email = ‘xyz@example.com';
$student>save();Genauso lassen sich mehrere Models auf einmal aktualisieren, wenn sie auf eine bestimmte Abfrage passen.
Ein vorhandenes Model löschen
Zum Löschen eines Models rufst du delete() auf:
$student = Student::find(1);
$student>delete();Löschen über den Schlüssel:
Student::destroy(1);
Student::destroy([1, 2, 3]);
Student::destroy(1, 2, 3);Und du kannst auf Basis einer Abfrage löschen.
$affectedRows = Student::where('votes', '>', 100)->delete();Verknüpfte Models
In jeder Datenbank gibt es Models, deren Werte voneinander abhängen, man nennt sie verknüpfte Models. Willst du zum Beispiel einen neuen Kommentar zu einem Beitrag anlegen, musst du post_id nicht von Hand setzen: Du legst den Kommentar direkt über das übergeordnete Model an.
$comment = new Comment(['message' => 'A new comment.']);
$post = Post::find(1);
$comment = $post->comments()->save($comment);Zugeordnete Models
Über die Methode associate() aktualisierst du ein Model, indem du den Fremdschlüssel darauf setzt. Auch Models mit mehreren Beziehungen lassen sich so zuordnen.
Model-Events
Bei jedem Schritt im Lebenszyklus eines Models – speichern, aktualisieren, löschen – feuert Eloquent ein Event, ein sogenanntes Model-Event. Es gibt unter anderem saving, saved, updating, updated, deleting, deleted, restoring und restored. Legst du einen neuen Datensatz an, greifen creating und created, existiert der Datensatz bereits, greifen stattdessen updating und updated.
Das Speichern über ein Event abbrechen
Gibt der Listener false zurück, wird die Aktion abgebrochen. Das gilt für jedes Event: deleting, updating, creating, saving.
Student::creating(function($student)
{
if ( ! $student>isValid()) return false;
});Event-Listener registrieren
Wie überall in Laravel braucht ein Event einen Service Provider, in dem es registriert wird, das gilt auch für Model-Events. Vorgesehen ist dafür der EventServiceProvider , der als fester Ort für die Bindings der Model-Events dient.
Beispiel:
public function boot(DispatcherContract $events)
{
parent::boot($events);
Student::creating(function($student)
{
//
});
}Model-Observer
Observer bündeln die Behandlung von Model-Events an einer Stelle. Eine Observer-Klasse enthält je eine Methode pro Model-Event.
class StudentObserver {
public function saving($model)
{
//
}
public function saved($model)
{
//
}
}Registrieren lässt sich ein Observer außerdem über die Methode observe:
User::observe(new UserObserver);Model-URLs erzeugen
Übergibst du ein Model an route() oder action(), setzt Laravel seinen Primärschlüssel in den URI ein. So entsteht die eindeutige URL des Models.
Route::get('student/{student}', 'StudentController@show');
action('StudentController@show', [$student]);Hier landet die ID des Students in der URL. Willst du stattdessen eine andere Eigenschaft in der erzeugten URL sehen, überschreibst du die Methode getRouteKey in deinem Model.
public function getRouteKey()
{
return $this->slug;
}Weitere Funktionen von Laravel Eloquent
Umwandeln in Arrays und JSON
Baust du eine API, gibst du die Ergebnisse fast immer als JSON aus – deine Models und ihre Beziehungen müssen also nach JSON oder Array wandern. Auch dafür bringt Laravel Eloquent alles mit. Ein Model samt seiner Beziehungen überführst du mit toArray() in ein Array.
$student = Student::with('roles')->first();
return $student->toArray();Und so wandelst du ein Model direkt in JSON um:
return Student::find(1)->toJson();Ein Model lässt sich auch unmittelbar aus einer Route zurückgeben. Sobald es in einen String umgewandelt wird, entsteht daraus JSON – du kannst Eloquent-Objekte also unverändert zurückgeben.
Route::get('student', function()
{
return Student::all();
});Geschützte Felder wie `personal_id` oder das Passwort gehören dabei nicht in die Ausgabe. Um sie zu verbergen, führst du sie unter `$hidden` in deinem Model auf.
Attribute casten
Willst du den Datentyp eines Attributs umwandeln, könntest du für jedes einen Mutator schreiben – das kostet Zeit und lädt zu Fehlern ein. Einfacher ist das Casting: Du trägst das Attribut in die Eigenschaft $casts deines Models ein. Weitere zulässige Cast-Typen sind integer, float, double, real, object, string, array.
Ein Beispiel:
protected $casts = [
'is_student' => 'boolean',
];Hier liegt is_student in der Datenbank in einem anderen Typ vor, beim Zugriff bekommst du aber immer einen boolean zurück.
Der Array-Cast ist besonders nützlich, wenn du mit einer Spalte arbeitest, die serialisiertes JSON enthält. Serialisiertes JSON heißt: Ein Objekt wurde als String kodiert. Steht in einer deiner Spalten solches JSON, wandelt der Array-Cast es beim Auslesen aus dem Eloquent-Model automatisch in ein PHP-Array um.
protected $casts = [
'options' => 'array',
];Datums-Mutatoren
Carbon ist eine international verbreitete Erweiterung von PHPs DateTime. Eloquent wandelt created_at und updated_at in Carbon-Instanzen um, die etliche nützliche Methoden mitbringen und die DateTime-Klasse von PHP erweitern. Willst du diese Umwandlung nicht automatisch, passt du sie leicht an: Du überschreibst dazu die Methode getDates in deinem Model. Um die Datumsmutation komplett abzuschalten, gibst du in der Methode `getDates` ein leeres Array zurück. Ein Beispiel:
public function getDates()
{
return ['created_at'];
}Gilt eine Spalte als Datum, hast du vier Möglichkeiten, sie zu füllen: einen UNIX-Timestamp, einen Datums-String (Y-m-d), ein Datum mit Uhrzeit oder eine DateTime- beziehungsweise Carbon-Instanz.
Accessoren und Mutatoren
Wie Getter und Setter in jeder anderen Sprache erlauben dir Accessoren und Mutatoren, Eloquent-Attribute zu formatieren, bevor du sie ausliest oder auf einer Model-Instanz setzt. Der Unterschied zwischen beiden: Accessoren greifen beim Lesen, Mutatoren beim Schreiben.
Einen Accessor legst du an, indem du in deinem Model eine Methode `getFooAttribute` definierst. Der Methodenname folgt dabei immer der CamelCase-Schreibweise, auch wenn die Spalte kleingeschrieben ist.
class User extends Model {
public function getFirstNameAttribute($value)
{
return ucfirst($value);
}
}Ein Mutator entsteht auf demselben Weg: Du nimmst `setFooAttribute` – und ja, auch hier gilt wieder CamelCase.
class User extends Model {
public function setFirstNameAttribute($value)
{
$this->attributes['first_name'] = strtolower($value);
}
}Soft Deletes
Ein Soft Delete entfernt den Datensatz nicht aus der Datenbank, sondern setzt einen eigenen Timestamp. `deleted_at` wird auf dem betreffenden Datensatz gefüllt. Aktivieren kannst du das, indem du das Trait SoftDeletes in dein Model einbindest.
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model {
use SoftDeletes;
protected $dates = ['deleted_at'];
}softDeletes() fügt in der Migration die Spalte deleted_at hinzu. Eine Migration ist nichts anderes, als deine Datenbank in PHP statt in SQL zu verwalten.
$table->softDeletes();Manchmal sollen die soft-gelöschten Datensätze in einer Abfrage trotzdem auftauchen. Dafür hängst du withTrashed() an die Abfrage.
Willst du ausschließlich soft-gelöschte Models im Ergebnis sehen, nimmst du die Methode onlyTrashed() .
$student = Student::onlyTrashed()->where('account_id', 1)->get();Sollen soft-gelöschte Models nach all diesen Operationen wieder aktiv werden, hilft dir die Methode restore().
$student->restore();restore() lässt sich auch direkt auf einer Abfrage aufrufen.
Student::withTrashed()->where('account_id', 1)->restore();Willst du ein soft-gelöschtes Model endgültig aus der Datenbank entfernen, hilft die Methode forceDelete() weiter.
$student->posts()->forceDelete();Ob ein Model gelöscht ist, prüfst du mit der Methode trashed().
if ($student->trashed())
{
//Todo
}Fazit
Laravel gehört zu den bekanntesten PHP-Frameworks, und Eloquent macht die Arbeit mit Datenbanken darin ausgesprochen bequem. In diesem Artikel haben wir die wichtigsten Funktionen von Laravel Eloquent durchgesehen. Es gibt noch etliche mehr, und nachlesen kannst du sie hier. Folge dem Link und sieh dir den vollen Funktionsumfang von Laravel Eloquent an.


