Eloquent in Laravel 8: die wichtigsten Funktionen des ORM

Eloquent in Laravel 8: die wichtigsten Funktionen des ORM
Eloquent, das mit dem bekannten PHP-Framework Laravel ausgeliefert wird, bietet einen eleganten und sehr effizienten Weg, mit der Datenbank zu sprechen. Websites werden durch immer mehr Anpassungen zunehmend komplexer, und damit auch die Datenbanken, die Entwickler dafür entwerfen müssen. Laravel Eloquent nimmt dir einen großen Teil dieser Arbeit ab. Es lässt dich sauber formatierten, gut lesbaren, wartbaren und gut dokumentierten Code schreiben. Genau dieser Funktionsumfang ist einer der Gründe für den Erfolg von Laravel.Dieser Artikel geht die wichtigsten Funktionen des Eloquent ORM durch.

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:

bash
php artisan list

Danach erscheinen alle Befehle mit einer kurzen Beschreibung auf dem Bildschirm. Brauchst du Hilfe zu einem bestimmten Befehl, stellst du ihm einfach „help“ voran. Beispiel:

bash
php artisan help migrate

Eloquent-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`:

bash
php artisan make: model Student

Die Grundstruktur eines Models sieht so aus:

php
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.

bash
php artisan make:model Student--migration
php artisan make:model Flight -m

Seeder, Factories, Controller und weitere Klassen erzeugst du, indem du dem Artisan-Befehl `make:model` die passenden Optionen mitgibst. Beispiele:

bash
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 -c

Diese Optionen lassen sich außerdem kombinieren, um mehrere Klassen auf einmal anzulegen.

bash
php artisan make:model Flight -mfsc

Ein 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.

php
$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:

php
$student = Student::find(1);

$student>delete();

Löschen über den Schlüssel:

php
Student::destroy(1);

Student::destroy([1, 2, 3]);

Student::destroy(1, 2, 3);

Und du kannst auf Basis einer Abfrage löschen.

php
$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.

php
$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.

php
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:

php
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.

php
class StudentObserver {

public function saving($model)
    {
        //
    }

public function saved($model)
    {
        //
    }

}

Registrieren lässt sich ein Observer außerdem über die Methode observe:

php
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.

php
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.

php
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.

php
$student = Student::with('roles')->first();

return $student->toArray();

Und so wandelst du ein Model direkt in JSON um:

php
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.

php
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:

php
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.

php
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:

php
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.

php
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.

php
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.

php
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.

php
$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() .

php
$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().

php
$student->restore();

restore() lässt sich auch direkt auf einer Abfrage aufrufen.

php
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.

php
$student->posts()->forceDelete();

Ob ein Model gelöscht ist, prüfst du mit der Methode trashed().

php
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.


LaravelPHP

Damien Flandrin Webentwickler seit 2010, Gründer von Gekkode und Email Impact. Jeder Artikel wird vor der Veröffentlichung an einem echten Projekt getestet. Kontakt
Newsletter

Neue Tests, Tutorials und Projekte, per E-Mail.

Reproduzierbare Tests, versionierter Code, datierte Ergebnisse. Niemals Spam.