> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Einführung in Eloquent

> Erläutert, wie Sie mit dem Laravel-ORM Eloquent Daten in Ihrer Datenbank verwalten.

## Was ist das Eloquent-ORM?

Laravel bringt mit Eloquent ein Object-Relational-Mapper (ORM) mit.
Eloquent erleichtert die Interaktion mit der Datenbank und setzt das **Active-Record-Muster** um.

Sie legen für jede Tabelle eine passende „Model"-Klasse an und arbeiten über das Modell mit den Datensätzen – zum Lesen, Einfügen, Aktualisieren oder Löschen.

<Info>
  Konfigurieren Sie vor der Nutzung von Eloquent Ihre Datenbankverbindung in `config/database.php`.
  Standardmäßig werden die `DB_*`-Werte aus der `.env`-Datei verwendet.
</Info>

## Modell erstellen

Ein neues Modell erzeugen Sie mit dem Artisan-Befehl `make:model`.

```shell theme={null}
php artisan make:model Post
```

Um gleichzeitig eine Migration zu erstellen, verwenden Sie die Option `-m`.

```shell theme={null}
php artisan make:model Post -m
```

Modelle werden im Verzeichnis `app/Models` abgelegt.

```php theme={null}
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    // ...
}
```

## Zuordnung von Modell und Tabelle

Eloquent leitet den Tabellennamen automatisch aus dem Klassennamen ab.
Der Tabellenname ist der Klassenname in Snake-Case und im Plural.

| Modellname             | Tabellenname              |
| ---------------------- | ------------------------- |
| `Post`                 | `posts`                   |
| `User`                 | `users`                   |
| `AirTrafficController` | `air_traffic_controllers` |

Passt der Tabellenname nicht zur Namenskonvention, geben Sie ihn über die Property `$table` explizit an.

```php theme={null}
class Post extends Model
{
    protected $table = 'blog_posts';
}
```

### Zeitstempel

Standardmäßig verwaltet Eloquent die Spalten `created_at` und `updated_at` automatisch.
Wenn Sie in der Migration `$table->timestamps()` einfügen, werden die Werte beim Speichern oder Aktualisieren automatisch gesetzt.

Um die automatische Zeitstempelverwaltung zu deaktivieren, setzen Sie `$timestamps` auf `false`.

```php theme={null}
class Post extends Model
{
    public $timestamps = false;
}
```

## Schutz vor Mass Assignment

Beim gleichzeitigen Zuweisen mehrerer Werte über Eloquent muss der Schutz vor Mass Assignment konfiguriert sein.

### fillable

Erlauben Sie die Zuweisung bestimmter Spalten über die Property `$fillable`.

```php theme={null}
class Post extends Model
{
    protected $fillable = [
        'user_id',
        'title',
        'body',
        'published',
    ];
}
```

### guarded

Umgekehrt geben Sie mit `$guarded` an, welche Spalten geschützt sind.

```php theme={null}
class Post extends Model
{
    // Nur der Primärschlüssel ist geschützt, alles andere ist erlaubt
    protected $guarded = ['id'];
}
```

<Warning>
  Ein leeres Array bei `$guarded` erlaubt die Zuweisung an alle Spalten.
  Übergeben Sie Nutzereingaben direkt, besteht die Gefahr, dass ungewollt Spalten überschrieben werden. Es empfiehlt sich daher, gezielt mit `$fillable` freizugeben.
</Warning>

## Ausführungsablauf einer Eloquent-Query

Nachfolgend sehen Sie, wie eine Abfrage wie `User::where()->get()` intern abläuft.

```mermaid theme={null}
flowchart LR
    A["User::where('active', true)"] --> B["Query Builder erstellen"]
    B --> C["->get() aufrufen"]
    C --> D["SQL erzeugen"]
    D --> E["Datenbank ausführen"]
    E --> F["Ergebnis in Eloquent-Modelle umwandeln"]
    F --> G["Als Collection zurückgeben"]
```

## Grundlegende CRUD-Operationen

### Datensätze lesen (Read)

Alle Datensätze abrufen:

```php theme={null}
use App\Models\Post;

$posts = Post::all();
```

Mit Bedingungen abfragen:

```php theme={null}
// Alle Beiträge mit published = true
$publishedPosts = Post::where('published', true)->get();

// Nur der erste Datensatz
$post = Post::where('published', true)->first();

// Ein Datensatz per ID
$post = Post::find(1);

// Nicht gefunden ⇒ 404-Antwort
$post = Post::findOrFail(1);
```

### Datensätze anlegen (Create)

Mit `create` fügen Sie einen Datensatz ein (die Property `$fillable` muss konfiguriert sein).

```php theme={null}
$post = Post::create([
    'title' => 'Mein erster Beitrag',
    'body' => 'Laravel ist ein großartiges Framework.',
    'published' => true,
]);
```

Alternativ instanziieren Sie das Modell und weisen die Werte einzeln zu.

```php theme={null}
$post = new Post;
$post->title = 'Mein erster Beitrag';
$post->body = 'Laravel ist ein großartiges Framework.';
$post->save();
```

### Datensätze aktualisieren (Update)

Laden Sie das Modell, ändern Sie den Wert und rufen Sie `save` auf.

```php theme={null}
$post = Post::find(1);
$post->title = 'Aktualisierter Titel';
$post->save();
```

Mit `update` aktualisieren Sie mehrere Spalten gleichzeitig.

```php theme={null}
Post::find(1)->update([
    'title' => 'Aktualisierter Titel',
    'published' => true,
]);
```

Mehrere Datensätze lassen sich per Bedingung gemeinsam aktualisieren.

```php theme={null}
Post::where('published', false)->update(['published' => true]);
```

### Datensätze löschen (Delete)

Rufen Sie `delete` auf einem Modell auf.

```php theme={null}
$post = Post::find(1);
$post->delete();
```

Alternativ können Sie direkt per ID löschen.

```php theme={null}
Post::destroy(1);

// Mehrere IDs zusammen löschen
Post::destroy([1, 2, 3]);
```

## Grundlegende Query-Methoden

| Methode                                      | Beschreibung                                      |
| -------------------------------------------- | ------------------------------------------------- |
| `Post::all()`                                | Alle Datensätze abrufen                           |
| `Post::find($id)`                            | Datensatz per ID abrufen (bei Nichtfinden `null`) |
| `Post::findOrFail($id)`                      | Datensatz per ID abrufen (bei Nichtfinden 404)    |
| `Post::where('column', 'value')->get()`      | Datensätze mit passender Bedingung abrufen        |
| `Post::where('column', 'value')->first()`    | Ersten passenden Datensatz abrufen                |
| `Post::where('column', 'value')->count()`    | Anzahl passender Datensätze                       |
| `Post::orderBy('created_at', 'desc')->get()` | Sortierung angeben                                |
| `Post::latest()->get()`                      | Nach `created_at` absteigend sortiert abrufen     |
| `Post::limit(10)->get()`                     | Begrenzte Anzahl abrufen                          |

## Praxisbeispiel: Datenverwaltung mit einem Post-Modell

Beispiel für einen Controller, der die per Migration erzeugte Tabelle `posts` verwaltet.

```php theme={null}
<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class PostController extends Controller
{
    // Beitragsliste anzeigen
    public function index(): View
    {
        $posts = Post::where('published', true)
            ->latest()
            ->get();

        return view('posts.index', ['posts' => $posts]);
    }

    // Beitrag anlegen
    public function store(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'title' => ['required', 'string', 'max:255'],
            'body' => ['required', 'string'],
            'published' => ['boolean'],
        ]);

        Post::create([
            ...$validated,
            'user_id' => $request->user()->id,
        ]);

        return redirect('/posts');
    }

    // Beitrag aktualisieren
    public function update(Request $request, Post $post): RedirectResponse
    {
        $validated = $request->validate([
            'title' => ['required', 'string', 'max:255'],
            'body' => ['required', 'string'],
        ]);

        $post->update($validated);

        return redirect('/posts');
    }

    // Beitrag löschen
    public function destroy(Post $post): RedirectResponse
    {
        $post->delete();

        return redirect('/posts');
    }
}
```

<Tip>
  Wenn Sie eine Controller-Methode mit dem Parameter `Post $post` versehen, lädt Laravel das Modell automatisch anhand des Route-Parameters (Route Model Binding).
  Sie müssen `Post::findOrFail($id)` also nicht selbst schreiben.
</Tip>

## Lebenszyklus der Modell-Events

Der folgende Ablauf zeigt, welche Events beim Aufruf von `save()` ausgelöst werden. Ob es sich um ein Neu-Anlegen oder ein Aktualisieren handelt, entscheidet, welche Events zwischen `saving` und `saved` gefeuert werden – letztere werden in beiden Fällen ausgelöst.

```mermaid theme={null}
flowchart TD
    A["Neue Instanz erzeugen"] --> B{"save()"}
    B --> I["Event: saving"]
    I -->|"Neu"| C["Event: creating"]
    C --> D["INSERT ausführen"]
    D --> E["Event: created"]
    I -->|"Update"| F["Event: updating"]
    F --> G["UPDATE ausführen"]
    G --> H["Event: updated"]
    E --> J["Event: saved"]
    H --> J
```

## Nächste Schritte

<Card title="Migrationen" icon="table" href="/de/migrations">
  Frischen Sie auf, wie Sie mit Migrationen Tabellen für Eloquent anlegen.
</Card>


## Related topics

- [Einführung in Eloquent-Relationen](/de/eloquent-relationships.md)
- [Eloquent-Collections](/de/eloquent-collections.md)
- [Einführung in die Authentifizierung](/de/authentication.md)
- [Eloquent-Serialisierung](/de/eloquent-serialization.md)
- [⚡ Einführung in Livewire 4 – Reaktive UIs ohne JavaScript](/de/blog/livewire-introduction.md)
