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

# Paginatie

> Uitleg over de paginatiefunctionaliteit van Laravel. Behandelt de verschillen tussen paginate(), simplePaginate() en cursorPaginate(), weergave in Blade, API-responses en het aanpassen van URL's.

## Wat is paginatie

De paginatie van Laravel is geïntegreerd met de querybuilder en Eloquent ORM en je kunt er zonder configuratie mee aan de slag. De huidige pagina wordt automatisch afgeleid uit de queryparameter `page` van het HTTP-verzoek en wordt ook automatisch toegevoegd aan de gegenereerde links.

De standaard-HTML is geschikt voor Tailwind CSS; je kunt ook kiezen voor Bootstrap CSS.

## Drie soorten paginatie

| Methode            | Returnwaarde           | Kenmerken                                                      |
| ------------------ | ---------------------- | -------------------------------------------------------------- |
| `paginate()`       | `LengthAwarePaginator` | Haalt het totale aantal op. Genereert paginanummerlinks        |
| `simplePaginate()` | `Paginator`            | Haalt het totale aantal niet op. Alleen "vorige" en "volgende" |
| `cursorPaginate()` | `CursorPaginator`      | Cursorgebaseerd. Optimaal voor grote hoeveelheden data         |

## Basisgebruik

### Paginatie met de querybuilder

```php theme={null}
use Illuminate\Support\Facades\DB;

// Haal 15 records per pagina op
$users = DB::table('users')->paginate(15);
```

### Paginatie met Eloquent

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

$users = User::paginate(15);

// Met voorwaarden
$users = User::where('votes', '>', 100)->paginate(15);
```

### simplePaginate

Als de count-query voor het totale aantal niet nodig is (alleen "vorige"- en "volgende"-links tonen), is `simplePaginate()` efficiënter.

```php theme={null}
$users = DB::table('users')->simplePaginate(15);
$users = User::where('active', true)->simplePaginate(15);
```

<Tip>
  Heb je geen weergave nodig in de trant van "record X van Y in totaal", kies dan `simplePaginate()`. Omdat `paginate()` een extra `COUNT(*)`-query uitvoert, is `simplePaginate()` sneller.
</Tip>

### cursorPaginate (cursorpaginatie)

Cursorpaginatie gebruikt een WHERE-clausule in plaats van een OFFSET-clausule en levert daardoor hoge prestaties bij grote hoeveelheden data. Het is bijzonder geschikt voor UI's met infinite scroll.

```php theme={null}
// orderBy is verplicht
$users = DB::table('users')->orderBy('id')->cursorPaginate(15);
$users = User::where('active', true)->cursorPaginate(15);
```

De gegenereerde URL bevat geen paginanummer maar een cursorstring.

```
http://example.com/users?cursor=eyJpZCI6MTUsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0
```

<Warning>
  Voor cursorpaginatie is `orderBy` verplicht. Bovendien moeten de sorteerkolommen tot de gepagineerde tabel behoren.
</Warning>

### OFFSET versus cursor

```sql theme={null}
-- paginate() / simplePaginate() — gebruikt OFFSET
SELECT * FROM users ORDER BY id ASC LIMIT 15 OFFSET 15;

-- cursorPaginate() — gebruikt een WHERE-clausule (index wordt benut)
SELECT * FROM users WHERE id > 15 ORDER BY id ASC LIMIT 15;
```

Cursorpaginatie benut indexen effectief en heeft als voordeel dat er minder snel dubbele of ontbrekende records optreden wanneer data vaak wordt toegevoegd of verwijderd. Je kunt echter geen paginanummerlinks genereren; alleen "vorige" en "volgende".

## Implementatie in een controller

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

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\View\View;

class UserController extends Controller
{
    public function index(): View
    {
        $users = User::orderBy('name')->paginate(20);

        return view('users.index', compact('users'));
    }
}
```

## Paginatielinks tonen in Blade

```blade theme={null}
<div class="container">
    @foreach ($users as $user)
        <p>{{ $user->name }}</p>
    @endforeach
</div>

{{-- Paginatielinks uitvoeren (geschikt voor Tailwind CSS) --}}
{{ $users->links() }}
```

De `links()`-methode genereert automatisch de HTML van de paginalinks. Er worden links getoond voor drie pagina's vóór en na de huidige pagina.

### Het aantal getoonde links aanpassen

Met `onEachSide()` wijzig je hoeveel links vóór en na de huidige pagina worden getoond.

```blade theme={null}
{{-- Toon vijf pagina's vóór en na de huidige pagina --}}
{{ $users->onEachSide(5)->links() }}
```

## Het aantal per pagina uit het request halen

```php theme={null}
public function index(Request $request): View
{
    $perPage = $request->integer('per_page', 15);
    $perPage = min(max($perPage, 1), 100); // Beperk tot het bereik 1–100

    $users = User::paginate($perPage);

    return view('users.index', compact('users'));
}
```

## Meerdere paginators op één pagina tonen

Als je twee paginators op hetzelfde scherm toont, botsen ze wanneer beide de `page`-parameter gebruiken. Wijzig de parameternaam via het derde argument.

```php theme={null}
$users = User::paginate(
    perPage: 15,
    columns: ['*'],
    pageName: 'users'
);

$posts = Post::paginate(
    perPage: 10,
    columns: ['*'],
    pageName: 'posts'
);
```

## URL's aanpassen

### De basis-URL wijzigen

```php theme={null}
$users = User::paginate(15);

// Genereer URL's in de vorm /admin/users?page=N
$users->withPath('/admin/users');
```

### Queryparameters toevoegen

```php theme={null}
// Voeg sort=votes toe aan elke paginalink
$users->appends(['sort' => 'votes']);

// Neem alle queryparameters van het huidige request over
$users->withQueryString();
```

### Een hashfragment toevoegen

```php theme={null}
// Voeg #users toe aan het einde van de URL
$users->fragment('users');
```

## API-responses (JSON-uitvoer)

Als je een paginator rechtstreeks vanuit een route of controller teruggeeft, wordt hij automatisch naar JSON geconverteerd.

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

Route::get('/api/users', function () {
    return User::paginate(15);
});
```

Het JSON-formaat van de response:

```json theme={null}
{
    "total": 50,
    "per_page": 15,
    "current_page": 1,
    "last_page": 4,
    "first_page_url": "http://example.com/api/users?page=1",
    "last_page_url": "http://example.com/api/users?page=4",
    "next_page_url": "http://example.com/api/users?page=2",
    "prev_page_url": null,
    "path": "http://example.com/api/users",
    "from": 1,
    "to": 15,
    "data": [
        { "id": 1, "name": "Taro Yamada" },
        { "id": 2, "name": "Hanako Suzuki" }
    ]
}
```

### Combineren met API-resources

Als je het resultaat van `paginate()` wilt wrappen in een API-resourcecollectie, geef je het door aan `UserResource::collection()`.

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

Route::get('/api/users', function () {
    $users = User::paginate(15);

    return UserResource::collection($users);
});
```

Als je een paginator doorgeeft aan `UserResource::collection()`, wordt de paginatie-informatie automatisch als metadata toegevoegd.

<Info>
  De JSON van `cursorPaginate()` bevat geen paginanummers maar `next_cursor` en `prev_cursor`. API-clients gebruiken deze waarden als `cursor`-parameter voor het volgende verzoek.
</Info>

## Aangepaste paginatieviews

### Direct in het viewbestand opgeven

```blade theme={null}
{{-- Links uitvoeren met een aangepaste view --}}
{{ $paginator->links('vendor.pagination.custom') }}

{{-- Extra data doorgeven --}}
{{ $paginator->links('vendor.pagination.custom', ['theme' => 'dark']) }}
```

### De standaardview wijzigen naar een aangepast bestand

Publiceer eerst de officiële views en pas ze daarna aan.

```shell theme={null}
php artisan vendor:publish --tag=laravel-pagination
```

In `resources/views/vendor/pagination/` worden de volgende bestanden aangemaakt.

* `tailwind.blade.php` — standaard (voor Tailwind CSS)
* `bootstrap-5.blade.php` — voor Bootstrap 5
* `simple-tailwind.blade.php` — voor simplePaginate
* ...

Bewerk `tailwind.blade.php` rechtstreeks, of maak een nieuwe view en stel die in via de `AppServiceProvider`.

```php theme={null}
use Illuminate\Pagination\Paginator;

public function boot(): void
{
    Paginator::defaultView('vendor.pagination.custom');
    Paginator::defaultSimpleView('vendor.pagination.simple-custom');
}
```

### Bootstrap CSS gebruiken

Gebruik je Bootstrap in plaats van Tailwind, dan stel je dat in via `boot()` in de `AppServiceProvider`.

```php theme={null}
use Illuminate\Pagination\Paginator;

public function boot(): void
{
    Paginator::useBootstrapFive(); // Bootstrap 5
    // Paginator::useBootstrapFour(); // Bootstrap 4
}
```

## Handmatig een paginator maken

Wil je paginatie toepassen op bestaande data zoals een array, dan instantieer je de paginatorklasse rechtstreeks.

```php theme={null}
use Illuminate\Pagination\LengthAwarePaginator;

$items = collect(range(1, 200))->map(fn ($i) => ['id' => $i, 'name' => "Item {$i}"]);

$perPage = 15;
$currentPage = request()->integer('page', 1);

$paginator = new LengthAwarePaginator(
    items: $items->forPage($currentPage, $perPage),
    total: $items->count(),
    perPage: $perPage,
    currentPage: $currentPage,
    options: ['path' => request()->url()]
);
```

## Veelgebruikte instantiemethodes

```php theme={null}
$paginator = User::paginate(15);

$paginator->currentPage();     // Huidig paginanummer
$paginator->lastPage();        // Laatste paginanummer (niet beschikbaar bij simplePaginate)
$paginator->total();           // Totaal aantal (niet beschikbaar bij simplePaginate)
$paginator->perPage();         // Aantal per pagina
$paginator->count();           // Aantal op de huidige pagina
$paginator->firstItem();       // Nummer van het eerste item op de huidige pagina
$paginator->lastItem();        // Nummer van het laatste item op de huidige pagina
$paginator->hasPages();        // Zijn er meerdere pagina's
$paginator->hasMorePages();    // Is er een volgende pagina
$paginator->onFirstPage();     // Is dit de eerste pagina
$paginator->onLastPage();      // Is dit de laatste pagina
$paginator->nextPageUrl();     // URL van de volgende pagina
$paginator->previousPageUrl(); // URL van de vorige pagina
$paginator->url(3);            // URL van pagina 3
$paginator->items();           // Array van items op de huidige pagina
```

## Samenvatting

<AccordionGroup>
  <Accordion title="Een paginatiemethode kiezen">
    * **`paginate()`** — wanneer je het totale aantal en paginanummerlinks nodig hebt (gangbare lijstschermen)
    * **`simplePaginate()`** — wanneer alleen "vorige"- en "volgende"-links volstaan (snel)
    * **`cursorPaginate()`** — bij grote hoeveelheden data, infinite scroll of frequente schrijfacties (beste prestaties)
  </Accordion>

  <Accordion title="Basispatroon voor weergave in Blade">
    ```blade theme={null}
    @foreach ($users as $user)
        <p>{{ $user->name }}</p>
    @endforeach

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

    Je geeft simpelweg het resultaat van `paginate()` door aan de view en voert de paginalinks uit met `links()`.
    De huidige pagina wordt automatisch gedetecteerd via de queryparameter `page`.
  </Accordion>

  <Accordion title="Paginatie in API's">
    Geef je een paginator rechtstreeks terug vanuit een route, dan wordt hij automatisch naar JSON geconverteerd.
    Om te combineren met API-resources geef je `UserResource::collection($paginator)` terug.
    De response bevat `data` (de array met records) en diverse metadata.
  </Accordion>
</AccordionGroup>


## Related topics

- [Laravel Scout](/nl/scout.md)
- [Upgradegids van Laravel 12 naar 13](/nl/blog/upgrade-12-to-13.md)
- [Laravel MCP](/nl/mcp.md)
