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

# Conditionable-trait

> De interne implementatie en toepassingspatronen van de methodes when() en unless()

## Wat is de Conditionable-trait?

De trait `Illuminate\Support\Traits\Conditionable` voegt de methodes `when()` en `unless()` toe aan een object. Kenmerkend is dat je op basis van voorwaarden kunt vertakken en toch je method chain kunt voortzetten.

<Info>
  De echte broncode staat in `src/Illuminate/Conditionable/Traits/Conditionable.php`. Je verwijst ernaar via de alias `Illuminate\Support\Traits\Conditionable`.
</Info>

Veel klassen in Laravel gebruiken deze trait, waaronder de QueryBuilder, EloquentBuilder, Mail en Notifications.

## Basisgebruik

### when() — uitvoeren als de voorwaarde waar is

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

$results = collect([1, 2, 3, 4, 5])
    ->when(true, function (Collection $collection) {
        return $collection->filter(fn ($n) => $n > 2);
    });
// [3, 4, 5]
```

Is de waarde van het eerste argument waar, dan wordt de callback in het tweede argument uitgevoerd. Is die onwaar, dan wordt de callback in het derde argument (de default) uitgevoerd.

```php theme={null}
$results = collect([1, 2, 3, 4, 5])
    ->when(false, function (Collection $collection) {
        return $collection->filter(fn ($n) => $n > 2);
    }, function (Collection $collection) {
        return $collection->filter(fn ($n) => $n < 3);
    });
// [1, 2]
```

### unless() — uitvoeren als de voorwaarde onwaar is

`unless()` is het omgekeerde van `when()`. De callback wordt uitgevoerd wanneer de voorwaarde onwaar is.

```php theme={null}
$results = collect([1, 2, 3, 4, 5])
    ->unless(false, function (Collection $collection) {
        return $collection->take(3);
    });
// [1, 2, 3]
```

## Waarom de method chain doorloopt

Geeft de callback `null` terug, dan wordt `$this` teruggegeven (het object dat de trait gebruikt). Geeft de callback iets anders dan `null` terug, dan wordt die returnwaarde teruggegeven.

```php theme={null}
// $this wordt teruggegeven, dus de chain loopt door
$query = User::query()
    ->when($request->has('active'), function ($query) {
        $query->where('active', true); // geeft void / null terug
    })
    ->when($request->filled('name'), function ($query) use ($request) {
        $query->where('name', 'like', "%{$request->name}%");
    })
    ->orderBy('created_at', 'desc');
```

In de broncode is dit als volgt geïmplementeerd:

```php theme={null}
if ($value) {
    return $callback($this, $value) ?? $this;
} elseif ($default) {
    return $default($this, $value) ?? $this;
}

return $this;
```

Geeft de callback expliciet een waarde terug, dan gaat die waarde door naar de volgende stap in de chain. Geeft hij niets terug (`null`), dan wordt `$this` teruggegeven.

## Aanroepen zonder argumenten — HigherOrderWhenProxy

Roep je `when()` aan zonder argumenten, dan krijg je een `HigherOrderWhenProxy` terug. Daarmee kun je de voorwaarde later instellen.

```php theme={null}
$query = User::query()
    ->when()->isActive()  // isActive() wordt als voorwaarde geëvalueerd
    ->where('role', 'admin');
```

Roep je de methode aan met één argument, dan krijg je een proxy terug die die waarde als voorwaarde vasthoudt.

```php theme={null}
// Eén argument: alleen de voorwaarde doorgeven en een proxy krijgen
$proxy = collect([1, 2, 3])->when($request->has('filter'));
// Met $proxy->methodName() wordt methodName() alleen aangeroepen als de voorwaarde waar is
```

## Een closure als waarde doorgeven

Geef je een closure door als eerste argument, dan wordt de returnwaarde van die closure als voorwaarde gebruikt.

```php theme={null}
$results = User::query()
    ->when(
        fn ($query) => $request->filled('role'),
        fn ($query) => $query->where('role', $request->role)
    )
    ->get();
```

Zo kun je de logica voor het evalueren van de voorwaarde in een callback onderbrengen.

## Typisch patroon bij de QueryBuilder

Dynamische query's opbouwen met `when()` is de meest voorkomende use case.

```php theme={null}
public function index(Request $request)
{
    $users = User::query()
        ->when($request->filled('search'), function ($query) use ($request) {
            $query->where('name', 'like', "%{$request->search}%")
                  ->orWhere('email', 'like', "%{$request->search}%");
        })
        ->when($request->filled('role'), fn ($q) => $q->where('role', $request->role))
        ->when($request->boolean('verified'), fn ($q) => $q->whereNotNull('email_verified_at'))
        ->when(
            $request->filled('sort'),
            fn ($q) => $q->orderBy($request->sort, $request->get('direction', 'asc')),
            fn ($q) => $q->latest()
        )
        ->paginate();

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

## Conditionable toepassen op je eigen klasse

Je hoeft de trait alleen te `use`-en en `when()` / `unless()` zijn beschikbaar.

```php theme={null}
namespace App\Services;

use Illuminate\Support\Traits\Conditionable;

class ReportBuilder
{
    use Conditionable;

    protected array $filters = [];
    protected bool $includeArchived = false;
    protected ?string $groupBy = null;

    public function withArchived(): static
    {
        $this->includeArchived = true;

        return $this;
    }

    public function groupBy(string $column): static
    {
        $this->groupBy = $column;

        return $this;
    }

    public function addFilter(string $column, mixed $value): static
    {
        $this->filters[$column] = $value;

        return $this;
    }

    public function build(): \Illuminate\Database\Eloquent\Builder
    {
        return Report::query()
            ->when($this->includeArchived, fn ($q) => $q->withTrashed())
            ->when($this->groupBy, fn ($q) => $q->groupBy($this->groupBy))
            ->when($this->filters, function ($q) {
                foreach ($this->filters as $column => $value) {
                    $q->where($column, $value);
                }
            });
    }
}
```

```php theme={null}
// Voorbeeldgebruik
$query = (new ReportBuilder)
    ->when($request->boolean('archived'), fn ($b) => $b->withArchived())
    ->when($request->filled('group'), fn ($b) => $b->groupBy($request->group))
    ->addFilter('status', 'published')
    ->build();
```

## Toepassing bij Mail, Notifications en Responses

`when()` kun je ook gebruiken bij het opbouwen van e-mails, notificaties en responses.

```php theme={null}
use Illuminate\Mail\Mailable;
use Illuminate\Support\Traits\Conditionable;

class OrderConfirmation extends Mailable
{
    public function build(): static
    {
        return $this
            ->subject('We hebben je bestelling ontvangen')
            ->view('emails.order.confirmation')
            ->when($this->order->hasDiscount(), function (Mailable $mail) {
                $mail->attach(storage_path('discounts/coupon.pdf'));
            })
            ->when(app()->environment('production'), function (Mailable $mail) {
                $mail->bcc('archive@example.com');
            });
    }
}
```

## Wanneer gebruik je tap() en wanneer when()?

`tap()` en `when()` lijken op elkaar, maar hebben een ander doel.

|              | `tap()`                         | `when()`                                                                 |
| ------------ | ------------------------------- | ------------------------------------------------------------------------ |
| Doel         | Bijeffecten (logging, debuggen) | Conditionele vertakking                                                  |
| Returnwaarde | Altijd `$this`                  | Afhankelijk van de voorwaarde `$this` of de returnwaarde van de callback |
| Voorwaarde   | Geen                            | Wel                                                                      |

```php theme={null}
// tap: voor bijeffecten. De returnwaarde is altijd $this
$user = User::find($id)
    ->tap(fn ($user) => Log::info("User {$user->id} loaded"));

// when: voor conditionele vertakking
$user = User::query()
    ->when($isAdmin, fn ($q) => $q->where('role', 'admin'))
    ->first();
```

<Tip>
  Wil je alleen iets doen in de chain voor debuggen of een bijeffect, gebruik dan `tap()`. Wil je de verwerking laten afhangen van een voorwaarde, gebruik dan `when()` / `unless()`.
</Tip>

## Volgende stap

<Card title="Higher order messages van collections" icon="layers" href="/nl/advanced/higher-order-messages">
  Leer hoe syntaxis als `$collection->map->method()` werkt en hoe je die in de praktijk gebruikt.
</Card>


## Related topics

- [Dumpable-trait](/nl/advanced/dumpable.md)
- [De tap()-helper en de Tappable-trait](/nl/advanced/tap.md)
- [InteractsWithData-trait](/nl/advanced/interacts-with-data.md)
- [InteractsWithTime-trait](/nl/advanced/interacts-with-time.md)
- [ForwardsCalls-trait](/nl/advanced/forwards-calls.md)
