> ## 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

> Het officiële pakket dat full-text en semantisch zoeken toevoegt aan Eloquent-modellen. Ondersteunt Meilisearch, Algolia, Typesense, Turbopuffer en een database-engine, en synchroniseert indexen automatisch via model observers.

## Inleiding

**Laravel Scout** is een eenvoudige, drivergebaseerde oplossing om full-text zoeken toe te voegen aan je [Eloquent-modellen](/nl/eloquent). Met behulp van model observers houdt Scout je Eloquent-records automatisch gesynchroniseerd met de zoekindexen.

Scout bevat een ingebouwde `database`-engine die rechtstreeks in je database zoekt met de full-text indexen van MySQL/PostgreSQL en `LIKE`-clausules — externe diensten zijn niet nodig. Heb je in een grootschalige productieomgeving typo-tolerantie, facetzoeken of geo-zoeken nodig, dan zijn de externe engines nuttig.

### Overzicht van ondersteunde engines

| Engine       | Kenmerken                               | Toepassing                   |
| ------------ | --------------------------------------- | ---------------------------- |
| `database`   | Full-text indexen van MySQL/PostgreSQL  | De meeste apps               |
| `collection` | Filteren in PHP (ook SQLite)            | Lokale ontwikkeling en tests |
| Meilisearch  | Open source, typo-tolerant, snel        | Productie                    |
| Algolia      | Cloud-SaaS, geavanceerde functies       | Productie                    |
| Typesense    | Open source, ondersteunt vectorzoeken   | Productie                    |
| Turbopuffer  | Full-text, semantisch en hybride zoeken | Productie                    |

```mermaid theme={null}
flowchart LR
  APP["Laravel-app<br>(Eloquent-modellen)"] -->|"save / delete"| SCOUT["Laravel Scout<br>(model observers)"]
  SCOUT -->|"Index synchroniseren"| ENGINE["Zoekengine<br>Meilisearch / Algolia / Typesense / Turbopuffer"]
  USER["Gebruiker"] -->|"Model::search()"| APP
  ENGINE -->|"Zoekresultaten"| APP
```

## Installatie

Installeer het pakket met Composer.

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

Publiceer na de installatie het configuratiebestand met het commando `vendor:publish`. Er wordt een `config/scout.php` gegenereerd.

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

Voeg tot slot de trait `Laravel\Scout\Searchable` toe aan de modellen die je doorzoekbaar wilt maken. Deze trait registreert een model observer en schakelt automatische synchronisatie met de zoekdriver in.

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

namespace App\Models;

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

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

### Queue-configuratie

Gebruik je een andere engine dan `database` of `collection`, dan raden we sterk aan om vóór het gebruik van Scout een [queuedriver](/nl/queues) te configureren. Door een queue worker te draaien, worden indexsynchronisaties op de achtergrond uitgevoerd, wat de responssnelheid van je webinterface flink verbetert.

Stel de optie `queue` in `config/scout.php` in op `true`.

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

Je kunt ook een verbindingsnaam en queuenaam opgeven.

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

Start na de configuratie een dedicated queue worker.

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

### Unieke jobs gebruiken

In applicaties met veel schrijfacties wil je mogelijk voorkomen dat er dubbele queue-jobs voor hetzelfde modelrecord op de queue belanden. Door in `config/scout.php` de jobklassen `MakeSearchableUniquely` en `RemoveFromSearchUniquely` te registreren, gebruik je unieke indexeringsjobs. Meestal stel je dit in via de `boot`-methode van een service provider.

```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);
```

Deze jobs gebruiken Laravels [unieke job-locks](#unieke-jobs-gebruiken) om te voorkomen dat er dubbele indexeringsoperaties worden gedispatcht voor een modelrecord dat al op de queue staat.

## Vereisten per driver

### Algolia

Gebruik je de Algolia-driver, stel dan de credentials `id` en `secret` in via `config/scout.php` en installeer de Algolia PHP SDK.

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

Voeg de credentials toe aan je `.env`-bestand.

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

#### Indexinstellingen

Bij Algolia kun je de indexinstellingen beheren 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)'],
        ],
    ],
],
```

Voer na de configuratie het commando `scout:sync-index-settings` uit om de instellingen naar Algolia te pushen.

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

### Meilisearch

[Meilisearch](https://www.meilisearch.com) is een snelle open-source zoekengine. Voor lokale ontwikkeling is Docker via [Laravel Sail](https://laravel.com/docs/sail#meilisearch) het eenvoudigst.

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

Gebruik je Sail niet, dan kun je hem rechtstreeks met Docker starten.

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

Installeer de Meilisearch PHP SDK.

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

Stel de driver en host in via je `.env`-bestand.

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

<Warning>
  Controleer bij het upgraden van Scout altijd ook de [breaking changes](https://github.com/meilisearch/Meilisearch/releases) van de Meilisearch-service zelf.
</Warning>

#### Indexinstellingen (Meilisearch)

Bij Meilisearch moet je kolommen waarop je met `where()` filtert vooraf registreren in `filterableAttributes`, en kolommen waarop je met `orderBy()` sorteert 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'],
        ],
    ],
],
```

Let op het datatype van numerieke kolommen. Meilisearch kan filteroperaties (`>`, `<` e.d.) alleen uitvoeren op data van het juiste type.

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

Voer na de configuratie het commando `scout:sync-index-settings` uit.

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

#### Semantisch en hybride zoeken (Meilisearch)

Om semantisch of hybride zoeken te gebruiken met Meilisearch, geef je in de indexinstellingen een embedder op en in de modelinstellingen de embedding-informatie.

```php theme={null}
'meilisearch' => [
    'index-settings' => [
        Article::class => [
            'embedders' => [
                'default' => [
                    'source' => 'userProvided',
                    'dimensions' => 1536,
                ],
            ],
        ],
    ],
    'model-settings' => [
        Article::class => [
            'embedding' => [
                'embedder' => 'default',
                'dimensions' => 1536,
            ],
        ],
    ],
],
```

De methode `toSearchableEmbedding` van je model geeft de brontekst terug die met de Laravel AI SDK wordt geëmbed, of een vooraf berekende embedding-array. Voer na de configuratie `scout:sync-index-settings` uit.

### Typesense

[Typesense](https://typesense.org) is een snelle open-source zoekengine met ondersteuning voor keyword-, semantisch, geo- en vectorzoeken.

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

Stel de verbindingsgegevens in via je `.env`-bestand.

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

Bij gebruik van Typesense moet je in de methode `toSearchableArray` de primaire sleutel van het model naar een string casten en de aanmaakdatum naar een UNIX-timestamp.

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

### Turbopuffer

[Turbopuffer](https://turbopuffer.com) is een zoekengine die full-text, semantisch en hybride zoeken ondersteunt. Om de Turbopuffer-driver te gebruiken stel je `SCOUT_DRIVER` en een API-sleutel in.

```ini theme={null}
SCOUT_DRIVER=turbopuffer
TURBOPUFFER_API_KEY=tpuf_...
TURBOPUFFER_REGION=gcp-us-central1
```

`TURBOPUFFER_REGION` is optioneel; de standaard is `gcp-us-central1`.

### Database-/collection-engine

De ideale optie als je zoeken wilt toevoegen zonder externe diensten.

De **database-engine** gebruikt de full-text indexen van MySQL/PostgreSQL en `LIKE`-clausules. Voor de meeste applicaties is dit voldoende.

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

#### Semantisch en hybride zoeken

De database-engine ondersteunt semantisch en hybride zoeken op PostgreSQL met de `pgvector`-extensie ingeschakeld. Voeg aan de tabel van je model een nullable vectorkolom en een full-text index toe. Scout slaat de embedding op ná het opslaan van het model, dus maak de vectorkolom nullable.

```php theme={null}
Schema::ensureVectorExtensionExists();

Schema::table('articles', function (Blueprint $table) {
    $table->vector('embedding', dimensions: 1536)->nullable();
    $table->vectorIndex('embedding');
    $table->fullText(['title', 'body']);
});
```

Definieer op het model de methode `toSearchableEmbedding`. Deze methode geeft de brontekst terug die Scout embedt, of een vooraf berekende embedding-array. De opslaglocatie is standaard de kolom `embedding`, maar dat kun je wijzigen met de methode `searchableEmbeddingColumn`.

De **collection-engine** filtert in PHP en werkt daardoor met alle databases die Laravel ondersteunt, inclusief SQLite. Bedoeld voor lokale ontwikkeling, tests en kleine datasets.

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

<Info>
  Anders dan bij externe engines is bij de database-engine geen handmatig indexbeheer nodig. Er wordt rechtstreeks in de databasetabel gezocht.
</Info>

### Turbopuffer-configuratie

Bij Turbopuffer definieer je per model de doorzoekbare attributen en het schema in `model-settings` van `config/scout.php`.

```php theme={null}
'turbopuffer' => [
    'model-settings' => [
        Article::class => [
            'searchable-attributes' => [
                'title' => 3,
                'body' => 1,
            ],
            'schema' => [
                'title' => ['type' => 'string', 'full_text_search' => true],
                'body' => ['type' => 'string', 'full_text_search' => true],
                'status' => ['type' => 'string'],
            ],
        ],
    ],
],
```

De getallen in `searchable-attributes` zijn relatieve BM25-gewichten. In het voorbeeld draagt een match in de titel drie keer zoveel bij aan de score als een match in de body. Gebruik je semantisch zoeken, voeg dan een `embedding`-configuratie en een vectorschema toe, en geef vanuit de methode `toSearchableEmbedding` van het model de brontekst of embedding-array terug.

```php theme={null}
'embedding' => [
    'attribute' => 'embedding',
    'dimensions' => 1536,
],

'schema' => [
    'embedding' => ['type' => '[1536]f32', 'ann' => true],
],
```

Gebruik je de native embeddings van Turbopuffer, dan zijn de Laravel AI SDK en `toSearchableEmbedding` niet nodig. Neem het bronattribuut voor de embedding op in de returnwaarde van `toSearchableArray` en configureer het als volgt.

```php theme={null}
'embedding' => [
    'driver' => 'turbopuffer',
    'attribute' => 'embedding_text',
],
```

## De Searchable-trait

### toSearchableArray() aanpassen

Standaard wordt alle data van `toArray()` van het model in de zoekindex opgeslagen. Wil je aanpassen welke data naar de index wordt gesynchroniseerd, override dan de methode `toSearchableArray`.

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

namespace App\Models;

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

class Post extends Model
{
    use Searchable;

    /**
     * Haal de indexeerbare data-array van het model op.
     *
     * @return array<string, mixed>
     */
    public function toSearchableArray(): array
    {
        $array = $this->toArray();

        // Data aanpassen...

        return $array;
    }
}
```

### De indexnaam aanpassen

Standaard wordt de tabelnaam van het model (meervoud) gebruikt als indexnaam. Je kunt dit aanpassen door de methode `searchableAs` te overriden.

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

### Zoekstrategieën voor de database-engine

Bij de database-engine geef je per kolom een efficiënte zoekstrategie op via PHP-attributen.

```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>
  Controleer voordat je `SearchUsingFullText` gebruikt of de betreffende kolommen een [full-text index](/nl/migrations) hebben.
</Warning>

### Voorwaardelijk doorzoekbaar maken

Wil je een model alleen onder bepaalde voorwaarden doorzoekbaar maken, definieer dan de methode `shouldBeSearchable`.

```php theme={null}
/**
 * Bepaal of dit model doorzoekbaar moet zijn.
 */
public function shouldBeSearchable(): bool
{
    return $this->isPublished();
}
```

<Warning>
  `shouldBeSearchable` werkt niet met de database-engine. Gebruik voor vergelijkbaar gedrag met de database-engine [where-clausules](#filteren-en-sorteren).
</Warning>

## Indexbeheer

<Info>
  De commando's in deze sectie zijn vooral relevant bij het gebruik van third-party engines zoals Algolia, Meilisearch en Typesense. Bij de database-engine is indexbeheer niet nodig.
</Info>

### Bestaande records importeren

Voer je Scout in bij een bestaand project, importeer dan de bestaande records in de index met het commando `scout:import`.

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

Je kunt ook via de queue op de achtergrond importeren.

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

### De index leegmaken

Om alle records van een model uit de zoekindex te verwijderen gebruik je `scout:flush`.

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

### Indexering pauzeren

Wil je tijdens Eloquent-operaties de synchronisatie met de zoekindex tijdelijk stopzetten, gebruik dan `withoutSyncingToSearch`.

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

Order::withoutSyncingToSearch(function () {
    // Modeloperaties hierbinnen worden niet naar de zoekindex gesynchroniseerd
});
```

### Records handmatig toevoegen en verwijderen

Je kunt via een query een collectie modellen aan de index toevoegen.

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

// Toevoegen via een relatie
$user->orders()->searchable();
```

Om records uit de index te verwijderen gebruik je `unsearchable`.

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

Als je een model `delete`t, wordt het ook automatisch uit de index verwijderd.

## Zoeken

Met de `search`-methode doorzoek je een model. Koppel `get` erachter om een collectie Eloquent-modellen op te halen.

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

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

Geef je het resultaat rechtstreeks terug vanuit een controller of route, dan wordt het automatisch omgezet naar JSON.

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

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

Heb je de ruwe zoekresultaten nodig, gebruik dan de `raw`-methode.

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

### Semantisch zoeken

Met de engines `database`, Meilisearch en Turbopuffer waarvoor embeddings zijn geconfigureerd, kun je records zoeken op basis van de betekenis van de query. Voeg de `semantic`-methode toe aan je zoekquery.

```php theme={null}
$articles = Article::search('hoe je een huis comfortabel houdt zonder elektriciteit')
    ->semantic()
    ->get();
```

Bij engines die dit ondersteunen kun je ook een minimale gelijkenisdrempel opgeven.

```php theme={null}
$articles = Article::search('opslag van hernieuwbare energie')
    ->semantic(minSimilarity: 0.6)
    ->get();
```

Om full-text en semantisch zoeken te combineren gebruik je de `hybrid`-methode. Via de argumenten geef je de relatieve gewichten van tekst- en semantisch zoeken op.

```php theme={null}
$articles = Article::search('opslag van hernieuwbare energie')
    ->hybrid(textWeight: 1, semanticWeight: 2)
    ->get();
```

### Paginatie

Met de `paginate`-methode pagineer je de zoekresultaten. Dit werkt net als paginatie bij gewone Eloquent-query's.

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

// Aantal items per pagina opgeven
$orders = Order::search('Star Trek')->paginate(15);
```

Bij de database-engine kun je ook `simplePaginate` gebruiken. Omdat het totale aantal niet wordt opgehaald, is dit efficiënt bij grote datasets.

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

Een weergavevoorbeeld in een Blade-template:

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

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

## Filteren en sorteren

Met de `where`-methode voeg je filtervoorwaarden toe aan de zoekquery.

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

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

// Match met een van de waarden in de array
$orders = Order::search('Star Trek')->whereIn('status', ['open', 'paid'])->get();

// Match met geen van de waarden in de array
$orders = Order::search('Star Trek')->whereNotIn('status', ['closed'])->get();
```

<Warning>
  Bij gebruik van Meilisearch moet je vóór het gebruik van `where` de [filterbare attributen](#indexinstellingen-meilisearch) configureren.
</Warning>

Met de `query`-methode kun je ook de Eloquent-query aanpassen.

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

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

## Eager loading

Bij het gebruik van Scout wordt eerst een lijst met ID's opgehaald bij de zoekengine, waarna de modellen via Eloquent worden opgehaald. Om het N+1-probleem te vermijden geef je met de `query`-methode eager loading op via `with()`.

```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();
```

Om relaties eager te laden bij een batchimport definieer je de methode `makeAllSearchableUsing`.

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

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

<Warning>
  `makeAllSearchableUsing` is mogelijk niet bruikbaar bij batchimports via de queue. Relaties worden niet hersteld wanneer modelcollecties in een queue-job worden verwerkt.
</Warning>

## Soft deletes

Als je geïndexeerde modellen [soft deletes](/nl/eloquent) gebruiken en je ook verwijderde modellen wilt doorzoeken, stel dan de optie `soft_delete` in `config/scout.php` in op `true`.

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

Eenmaal ingeschakeld kun je met `withTrashed` en `onlyTrashed` verwijderde records doorzoeken.

```php theme={null}
// Zoeken inclusief verwijderde records
$orders = Order::search('Star Trek')->withTrashed()->get();

// Alleen verwijderde records doorzoeken
$orders = Order::search('Star Trek')->onlyTrashed()->get();
```

## Custom engines

Als de ingebouwde zoekengines niet aan je behoeften voldoen, kun je een eigen custom engine implementeren. Een custom engine erft van de abstracte klasse `Laravel\Scout\Engines\Engine` en moet de volgende acht methoden implementeren.

```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);
```

Bekijk als referentie voor de implementatie de klasse `Laravel\Scout\Engines\AlgoliaEngine`.

Je registreert je custom engine bij Scout in de `boot`-methode van `App\Providers\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;
    });
}
```

Na registratie geef je hem op als driver in `config/scout.php`.

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

## Gerelateerde pagina's

<Card title="Eloquent ORM" icon="database" href="/nl/eloquent">
  Bekijk de basisprincipes van Eloquent-modellen.
</Card>

<Card title="Eloquent-relaties" icon="link" href="/nl/eloquent-relationships">
  Bekijk het definiëren van relaties en eager loading.
</Card>

<Card title="Queues" icon="clock" href="/nl/queues">
  Scout kan samen met queues de index op de achtergrond bijwerken.
</Card>


## Related topics

- [Zoeken](/nl/search.md)
- [MongoDB](/nl/mongodb.md)
- [Laravel Sail](/nl/sail.md)
- [Laravel-updates van augustus 2026](/nl/blog/changelog/202608.md)
- [Laravel-updates van maart 2026](/nl/blog/changelog/202603.md)
