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

# Laravel Scout

> Das offizielle Paket, das Eloquent-Modellen Volltextsuche hinzufügt. Unterstützt Meilisearch, Algolia, Typesense und Datenbank-Engines und synchronisiert Indizes über Modell-Observer automatisch.

## Einführung

**Laravel Scout** ist eine einfache, treiber-basierte Lösung, um [Eloquent-Modellen](/de/eloquent) Volltextsuche hinzuzufügen. Über Modell-Observer werden Eloquent-Datensätze automatisch mit dem Suchindex synchronisiert.

Scout bringt eine integrierte `database`-Engine mit, die Volltextindizes und `LIKE`-Klauseln von MySQL/PostgreSQL nutzt – ohne externen Dienst. Für große Produktivumgebungen mit Tippfehler-Toleranz, Facettensuche oder Geo-Suche sind externe Engines im Vorteil.

### Übersicht der Engines

| Engine       | Merkmale                                 | Anwendung                   |
| ------------ | ---------------------------------------- | --------------------------- |
| `database`   | Volltextindex von MySQL/PostgreSQL       | Für die meisten Anwendungen |
| `collection` | Filterung in PHP (auch SQLite)           | Lokale Entwicklung / Tests  |
| Meilisearch  | Open Source, tippfehlertolerant, schnell | Produktion                  |
| Algolia      | Cloud-SaaS mit vielen Funktionen         | Produktion                  |
| Typesense    | Open Source, unterstützt Vektorsuche     | Produktion                  |

```mermaid theme={null}
flowchart LR
  APP["Laravel-Anwendung<br>(Eloquent-Modelle)"] -->|"save / delete"| SCOUT["Laravel Scout<br>(Modell-Observer)"]
  SCOUT -->|"Index-Synchronisation"| ENGINE["Such-Engine<br>Meilisearch / Algolia / Typesense"]
  USER["Benutzer"] -->|"Model::search()"| APP
  ENGINE -->|"Suchergebnisse"| APP
```

## Installation

Installieren Sie das Paket mit Composer.

```shell theme={null}
composer require laravel/scout
```

Veröffentlichen Sie die Konfiguration mit `vendor:publish`. Dabei entsteht `config/scout.php`.

```shell theme={null}
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
```

Ergänzen Sie schließlich das Trait `Laravel\Scout\Searchable` in jedem Modell, das durchsuchbar sein soll. Das Trait registriert einen Model-Observer und aktiviert die automatische Synchronisation mit dem Suchtreiber.

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

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Post extends Model
{
    use Searchable;
}
```

### Queues konfigurieren

Für alle Engines außer `database` und `collection` empfehlen wir dringend, [Queues](/de/queues) einzurichten. Ein Worker verlagert Index-Synchronisationen in den Hintergrund und verbessert die Reaktionszeit der Weboberfläche erheblich.

Setzen Sie in `config/scout.php` die Option `queue` auf `true`.

```php theme={null}
'queue' => true,
```

Verbindung und Queue-Name lassen sich angeben.

```php theme={null}
'queue' => [
    'connection' => 'redis',
    'queue' => 'scout'
],
```

Starten Sie einen dedizierten Worker.

```shell theme={null}
php artisan queue:work redis --queue=scout
```

### Unique Jobs verwenden

In schreiblastigen Anwendungen möchten Sie duplizierte Index-Jobs für denselben Datensatz vermeiden. Registrieren Sie in `config/scout.php` – üblicherweise in der `boot`-Methode eines Service-Providers – die Job-Klassen `MakeSearchableUniquely` und `RemoveFromSearchUniquely`.

```php theme={null}
use Laravel\Scout\Jobs\MakeSearchableUniquely;
use Laravel\Scout\Jobs\RemoveFromSearchUniquely;
use Laravel\Scout\Scout;

Scout::makeSearchableUsing(MakeSearchableUniquely::class);
Scout::removeFromSearchUsing(RemoveFromSearchUniquely::class);
```

Diese Jobs nutzen Laravels [Unique-Job-Locks](/de/queues#unique-jobs), um doppelte Index-Operationen für denselben Datensatz zu vermeiden.

## Voraussetzungen der Treiber

### Algolia

Für Algolia setzen Sie in `config/scout.php` `id` und `secret` und installieren das Algolia-PHP-SDK.

```shell theme={null}
composer require algolia/algoliasearch-client-php
```

In der `.env`:

```ini theme={null}
ALGOLIA_APP_ID=your-app-id
ALGOLIA_SECRET=your-secret-key
```

#### Index-Konfiguration

Bei Algolia verwalten Sie Index-Einstellungen in `config/scout.php`.

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

'algolia' => [
    'id' => env('ALGOLIA_APP_ID', ''),
    'secret' => env('ALGOLIA_SECRET', ''),
    'index-settings' => [
        User::class => [
            'searchableAttributes' => ['id', 'name', 'email'],
            'attributesForFaceting' => ['filterOnly(email)'],
        ],
    ],
],
```

Synchronisieren Sie die Konfiguration mit `scout:sync-index-settings`.

```shell theme={null}
php artisan scout:sync-index-settings
```

### Meilisearch

[Meilisearch](https://www.meilisearch.com) ist eine schnelle Open-Source-Such-Engine. Am einfachsten läuft sie lokal via [Laravel Sail](https://laravel.com/docs/sail#meilisearch).

```shell theme={null}
# Mit Laravel Sail
./vendor/bin/sail up -d meilisearch
```

Ohne Sail direkt via Docker:

```shell theme={null}
docker run -it --rm \
    -p 7700:7700 \
    getmeili/meilisearch:latest \
    meilisearch --master-key="masterKey"
```

Installieren Sie das PHP-SDK.

```shell theme={null}
composer require meilisearch/meilisearch-php http-interop/http-factory-guzzle
```

`.env`:

```ini theme={null}
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=masterKey
```

<Warning>
  Beim Upgrade von Scout prüfen Sie stets auch die [Breaking Changes](https://github.com/meilisearch/Meilisearch/releases) von Meilisearch selbst.
</Warning>

#### Index-Konfiguration (Meilisearch)

Für Filter mit `where()` müssen Sie die Spalten in `filterableAttributes` eintragen; für Sortierungen mit `orderBy()` in `sortableAttributes`.

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

'meilisearch' => [
    'host' => env('MEILISEARCH_HOST', 'http://localhost:7700'),
    'key' => env('MEILISEARCH_KEY', null),
    'index-settings' => [
        User::class => [
            'filterableAttributes' => ['id', 'name', 'email'],
            'sortableAttributes' => ['created_at'],
        ],
    ],
],
```

Beachten Sie die Datentypen numerischer Spalten. Meilisearch führt Filteroperationen (`>`, `<` etc.) nur bei korrekt typisierten Werten aus.

```php theme={null}
public function toSearchableArray(): array
{
    return [
        'id' => (int) $this->id,
        'name' => $this->name,
        'price' => (float) $this->price,
    ];
}
```

Anschließend `scout:sync-index-settings` ausführen.

```shell theme={null}
php artisan scout:sync-index-settings
```

### Typesense

[Typesense](https://typesense.org) ist eine schnelle Open-Source-Such-Engine mit Keyword-, semantischer, Geo- und Vektorsuche.

```shell theme={null}
composer require typesense/typesense-php
```

`.env`:

```ini theme={null}
SCOUT_DRIVER=typesense
TYPESENSE_API_KEY=masterKey
TYPESENSE_HOST=localhost
TYPESENSE_PORT=8108
TYPESENSE_PATH=
TYPESENSE_PROTOCOL=http
```

Bei Typesense müssen Sie in `toSearchableArray` den Primärschlüssel als String und `created_at` als Unix-Timestamp casten.

```php theme={null}
public function toSearchableArray(): array
{
    return array_merge($this->toArray(), [
        'id' => (string) $this->id,
        'created_at' => $this->created_at->timestamp,
    ]);
}
```

### Datenbank-/Collection-Engine

Ideal, wenn Sie ohne externen Dienst suchen möchten.

Die **Datenbank-Engine** nutzt Volltextindizes und `LIKE`-Klauseln von MySQL/PostgreSQL und reicht für die meisten Anwendungen.

```ini theme={null}
SCOUT_DRIVER=database
```

Die **Collection-Engine** filtert in PHP und funktioniert auf allen von Laravel unterstützten Datenbanken (auch SQLite). Ideal für lokale Entwicklung, Tests und kleine Datensätze.

```ini theme={null}
SCOUT_DRIVER=collection
```

<Info>
  Anders als bei externen Engines müssen Sie bei der Datenbank-Engine keinen Index manuell pflegen. Es wird direkt in der Tabelle gesucht.
</Info>

## Das Trait `Searchable`

### `toSearchableArray()` anpassen

Standardmäßig werden alle Daten aus `toArray()` in den Suchindex geschrieben. Um die Daten zu steuern, überschreiben Sie `toSearchableArray`.

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

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Post extends Model
{
    use Searchable;

    /**
     * Gibt die für den Index vorgesehenen Daten des Modells zurück.
     *
     * @return array<string, mixed>
     */
    public function toSearchableArray(): array
    {
        $array = $this->toArray();

        // Daten anpassen...

        return $array;
    }
}
```

### Indexnamen anpassen

Standardmäßig wird der Tabellenname (in der Pluralform) als Index verwendet. Über `searchableAs` passen Sie ihn an.

```php theme={null}
public function searchableAs(): string
{
    return 'posts_index';
}
```

### Suchstrategie für die Datenbank-Engine

Bei der Datenbank-Engine legen Sie pro Spalte über PHP-Attribute eine effiziente Suchstrategie fest.

```php theme={null}
use Laravel\Scout\Attributes\SearchUsingFullText;
use Laravel\Scout\Attributes\SearchUsingPrefix;

#[SearchUsingPrefix(['id', 'email'])]
#[SearchUsingFullText(['bio'])]
public function toSearchableArray(): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'bio' => $this->bio,
    ];
}
```

<Warning>
  Bevor Sie `SearchUsingFullText` verwenden, achten Sie darauf, dass die Zielspalte einen [Volltextindex](/de/migrations) besitzt.
</Warning>

### Bedingt durchsuchbar

Um ein Modell nur unter bestimmten Bedingungen durchsuchbar zu machen, definieren Sie `shouldBeSearchable`.

```php theme={null}
/**
 * Entscheidet, ob das Modell durchsuchbar sein soll.
 */
public function shouldBeSearchable(): bool
{
    return $this->isPublished();
}
```

<Warning>
  `shouldBeSearchable` funktioniert nicht mit der Datenbank-Engine. Verwenden Sie dort [where-Klauseln](#filtern-und-sortieren).
</Warning>

## Index verwalten

<Info>
  Die Befehle in diesem Abschnitt sind vor allem für externe Engines (Algolia, Meilisearch, Typesense) relevant. Bei der Datenbank-Engine ist keine Index-Verwaltung nötig.
</Info>

### Vorhandene Datensätze importieren

Wenn Sie Scout in ein bestehendes Projekt einführen, importieren Sie vorhandene Datensätze mit `scout:import`.

```shell theme={null}
php artisan scout:import "App\Models\Post"
```

Der Import kann auch als Queue-Job laufen.

```shell theme={null}
php artisan scout:queue-import "App\Models\Post" --chunk=500
```

### Index leeren

Mit `scout:flush` entfernen Sie alle Datensätze eines Modells aus dem Suchindex.

```shell theme={null}
php artisan scout:flush "App\Models\Post"
```

### Index-Synchronisation pausieren

Um während Eloquent-Operationen die Sync mit dem Index zu unterbrechen, nutzen Sie `withoutSyncingToSearch`.

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

Order::withoutSyncingToSearch(function () {
    // Die Modell-Operationen darin synchronisieren nicht in den Index.
});
```

### Datensätze manuell hinzufügen/entfernen

Sie können anhand einer Abfrage Modelle in den Index aufnehmen.

```php theme={null}
// Ergebnisse einer Abfrage
Order::where('price', '>', 100)->searchable();

// Über eine Beziehung
$user->orders()->searchable();
```

Mit `unsearchable` entfernen Sie Datensätze wieder.

```php theme={null}
Order::where('price', '>', 100)->unsearchable();
```

Beim Aufruf von `delete` wird der Datensatz automatisch aus dem Index entfernt.

## Suche

Mit `search` durchsuchen Sie Modelle. Hängen Sie `get` an, um eine Eloquent-Collection zu erhalten.

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

$orders = Order::search('Star Trek')->get();
```

Aus Controllern oder Routen direkt zurückgegeben, wird das Ergebnis automatisch als JSON serialisiert.

```php theme={null}
use Illuminate\Http\Request;

Route::get('/search', function (Request $request) {
    return Order::search($request->search)->get();
});
```

Für die Rohdaten der Suche verwenden Sie `raw`.

```php theme={null}
$orders = Order::search('Star Trek')->raw();
```

### Pagination

Mit `paginate` paginieren Sie Ergebnisse wie sonst auch.

```php theme={null}
$orders = Order::search('Star Trek')->paginate();

// Datensätze pro Seite
$orders = Order::search('Star Trek')->paginate(15);
```

Mit der Datenbank-Engine ist auch `simplePaginate` verfügbar. Da keine Gesamtzahl ermittelt wird, ist das bei großen Datenmengen effizienter.

```php theme={null}
$orders = Order::search('Star Trek')->simplePaginate(15);
```

Anzeige in Blade:

```html theme={null}
<div class="container">
    @foreach ($orders as $order)
        {{ $order->price }}
    @endforeach
</div>

{{ $orders->links() }}
```

## Filtern und sortieren

Mit `where` schränken Sie die Suche ein.

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

// Gleichheit
$orders = Order::search('Star Trek')->where('user_id', 1)->get();

// In einer Menge
$orders = Order::search('Star Trek')->whereIn('status', ['open', 'paid'])->get();

// Nicht in einer Menge
$orders = Order::search('Star Trek')->whereNotIn('status', ['closed'])->get();
```

<Warning>
  Bei Meilisearch müssen Sie vor dem Einsatz von `where` die [filterbaren Attribute](#index-konfiguration-meilisearch) definieren.
</Warning>

Mit `query` passen Sie die Eloquent-Abfrage an.

```php theme={null}
use Illuminate\Database\Eloquent\Builder;

$orders = Order::search('Star Trek')
    ->query(fn (Builder $query) => $query->with('invoices'))
    ->get();
```

## Eager Loading

Scout holt zunächst die IDs aus der Such-Engine und dann die Modelle über Eloquent. Um N+1-Probleme zu vermeiden, geben Sie in `query` mit `with()` Eager Loading an.

```php theme={null}
use App\Models\Order;
use Illuminate\Database\Eloquent\Builder;

$orders = Order::search('Star Trek')
    ->query(fn (Builder $query) => $query->with(['invoices', 'user']))
    ->get();
```

Für Eager Loading bei Batch-Imports definieren Sie `makeAllSearchableUsing`.

```php theme={null}
use Illuminate\Database\Eloquent\Builder;

protected function makeAllSearchableUsing(Builder $query): Builder
{
    return $query->with('author');
}
```

<Warning>
  Bei queue-basierten Batch-Imports kann `makeAllSearchableUsing` nicht immer verwendet werden. Beziehungen werden im Queue-Job für eine Modell-Collection ggf. nicht wiederhergestellt.
</Warning>

## Soft Deletes

Verwendet Ihr indiziertes Modell [Soft Deletes](/de/eloquent) und wollen Sie auch gelöschte Datensätze suchen, setzen Sie in `config/scout.php` `soft_delete` auf `true`.

```php theme={null}
'soft_delete' => true,
```

Danach nutzen Sie `withTrashed` bzw. `onlyTrashed`.

```php theme={null}
// Auch gelöschte
$orders = Order::search('Star Trek')->withTrashed()->get();

// Nur gelöschte
$orders = Order::search('Star Trek')->onlyTrashed()->get();
```

## Eigene Engines

Reichen die eingebauten Engines nicht aus, implementieren Sie eine eigene. Erben Sie von der abstrakten Klasse `Laravel\Scout\Engines\Engine` und implementieren Sie folgende Methoden:

```php theme={null}
use Laravel\Scout\Builder;

abstract public function update($models);
abstract public function delete($models);
abstract public function search(Builder $builder);
abstract public function paginate(Builder $builder, $perPage, $page);
abstract public function mapIds($results);
abstract public function map(Builder $builder, $results, $model);
abstract public function getTotalCount($results);
abstract public function flush($model);
```

Als Vorlage können Sie sich die Klasse `Laravel\Scout\Engines\AlgoliaEngine` ansehen.

Registrieren Sie die Engine in der `boot`-Methode Ihres `AppServiceProvider`.

```php theme={null}
use App\ScoutExtensions\MySqlSearchEngine;
use Laravel\Scout\EngineManager;

public function boot(): void
{
    resolve(EngineManager::class)->extend('mysql', function () {
        return new MySqlSearchEngine;
    });
}
```

Nach der Registrierung wählen Sie sie in `config/scout.php` als Treiber aus.

```php theme={null}
'driver' => 'mysql',
```

## Verwandte Seiten

<Card title="Eloquent ORM" icon="database" href="/de/eloquent">
  Grundlagen der Eloquent-Modelle.
</Card>

<Card title="Eloquent-Beziehungen" icon="link" href="/de/eloquent-relationships">
  Definition von Beziehungen und Eager Loading.
</Card>

<Card title="Queues" icon="clock" href="/de/queues">
  Scout kann Indizes zusammen mit Queues im Hintergrund aktualisieren.
</Card>


## Related topics

- [Suche](/de/search.md)
- [MongoDB](/de/mongodb.md)
- [Laravel Sail](/de/sail.md)
- [Laravel-Updates März 2026](/de/blog/changelog/202603.md)
- [Laravel-Paketentwicklung](/de/advanced/package-development.md)
