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

# Helper tap() et trait Tappable

> Découvrez l'utilisation et les patterns d'implémentation du helper tap() et du trait Illuminate\Support\Traits\Tappable de Laravel.

## Qu'est-ce que tap()

`tap()` est un helper qui permet « d'utiliser une valeur tout en la renvoyant telle quelle ». Il sert à insérer un effet de bord.

L'implémentation dans `Illuminate\Support\helpers.php` est simple.

```php theme={null}
function tap($value, $callback = null)
{
    if (is_null($callback)) {
        return new HigherOrderTapProxy($value);
    }

    $callback($value);

    return $value;
}
```

```mermaid theme={null}
flowchart TD
    A["Appel de tap(value, callback)"] --> B{"callback est-il null ?"}
    B -- Oui --> C["Retourne un HigherOrderTapProxy"]
    B -- Non --> D["Exécute callback(value)"]
    D --> E["Retourne la valeur d'origine"]
```

<Info>
  `tap()` ignore la valeur retournée par le callback. La valeur retournée est toujours la valeur d'origine.
</Info>

## Utilisation de base

L'usage le plus courant : recevoir une valeur, la traiter, puis la renvoyer telle quelle.

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

$user = tap(User::query()->latest()->firstOrFail(), function (User $model) {
    $model->update(['last_seen_at' => now()]);
});

// C'est $user qui est renvoyé, indépendamment de la valeur de retour d'update()
```

Sans callback, un `HigherOrderTapProxy` est renvoyé, ce qui permet d'enchaîner directement des appels de méthode.

```php theme={null}
$updatedUser = tap($user)->update([
    'name' => $name,
    'email' => $email,
]);

// L'instance User d'origine est renvoyée, pas la valeur de retour d'update()
```

## Cas d'utilisation fréquents

### Insérer une sortie de débogage

```php theme={null}
$result = tap($query->get(), function ($users) {
    logger()->debug('Fetched users', ['count' => $users->count()]);
});
```

### Injecter des logs ou des événements dans une chaîne

```php theme={null}
$order = tap(Order::create($payload), function (Order $order) {
    event(new OrderCreated($order));
    logger()->info('Order created', ['id' => $order->id]);
});
```

### Exécuter uniquement des effets de bord sans changer la valeur retournée

```php theme={null}
$response = tap($service->handle($request), function ($response) {
    \Illuminate\Support\Facades\Cache::increment('service_handle_success_total');
});
```

<Tip>
  Si vous souhaitez transformer la valeur retournée, utilisez `with()` ou une affectation de variable classique. Réserver `tap()` aux effets de bord améliore la lisibilité.
</Tip>

## Qu'est-ce que le trait Tappable

En faisant `use Illuminate\Support\Traits\Tappable`, vous ajoutez une méthode `tap()` à votre classe.

```php theme={null}
trait Tappable
{
    public function tap($callback = null)
    {
        return tap($this, $callback);
    }
}
```

Elle fournit donc une version méthode d'instance du helper `tap()`.

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

class ReportBuilder
{
    use Tappable;
}

$builder = new ReportBuilder();

$builder = $builder->tap(function (ReportBuilder $instance) {
    logger()->debug('builder initialized');
});
```

## Utilisation en développement de packages

`Tappable` est pratique pour glisser un effet de bord au milieu d'une API fluide. Associé à `Macroable` et `Conditionable`, vous pouvez créer un builder extensible dans l'esprit Laravel.

<Steps>
  <Step title="Créer une classe fluide">
    ```php theme={null}
    use Illuminate\Support\Traits\Conditionable;
    use Illuminate\Support\Traits\Macroable;
    use Illuminate\Support\Traits\Tappable;

    class QueryPresetBuilder
    {
        use Macroable;
        use Conditionable;
        use Tappable;

        protected array $filters = [];

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

            return $this;
        }

        public function toArray(): array
        {
            return $this->filters;
        }
    }
    ```
  </Step>

  <Step title="Combiner Macroable, Conditionable et Tappable">
    ```php theme={null}
    QueryPresetBuilder::macro('forActiveUsers', function () {
        /** @var QueryPresetBuilder $this */
        return $this->where('active', true);
    });

    $filters = (new QueryPresetBuilder)
        ->forActiveUsers()
        ->when($request->filled('role'), fn ($builder) => $builder->where('role', $request->role))
        ->tap(fn ($builder) => logger()->debug('current filters', $builder->toArray()))
        ->toArray();
    ```
  </Step>
</Steps>

Pages associées :

* [Trait Macroable](/fr/advanced/macroable)
* [Trait Conditionable](/fr/advanced/conditionable)
* [VOICEVOX for Laravel](/fr/packages/laravel-voicevox) — un exemple concret où l'on ajuste `TalkAudioQuery` ou `SongAudioQuery` via `tap()` avant de les passer à `generate()`.

## Utilisations dans le cœur de Laravel

Le cœur de Laravel utilise réellement `tap()` / `Tappable`.

* `Illuminate\Routing\Router` combine `Macroable` et `Tappable`.
* `Router::respondWithRoute()` utilise `tap($route)->bind(...)` sans callback : après l'exécution de `bind()`, la `$route` d'origine est renvoyée.
* `Router::prepareResponse()` utilise `tap(..., fn (...) => event(...))` pour déclencher un événement après la conversion de la réponse.
* `Illuminate\Testing\Fluent\Concerns\Has` implémente une aide aux assertions via la chaîne `->tap(...)->first(...)->etc()`.

```php theme={null}
// Extrait de Illuminate\Routing\Router
$route = tap($this->routes->getByName($name))->bind($this->currentRequest);

return tap(static::toResponse($request, $response), function ($response) use ($request) {
    $this->events->dispatch(new ResponsePrepared($request, $response));
});
```

<Info>
  Pris isolément, `tap()` est un petit helper, mais combiné à `Macroable` et `Conditionable`, il facilite l'écriture de chaînes de méthodes lisibles très fréquentes dans Laravel.
</Info>

## Étapes suivantes

<Columns cols={2}>
  <Card title="Trait Macroable" icon="puzzle-piece" href="/fr/advanced/macroable">
    Découvrez la conception permettant d'ajouter des méthodes personnalisées aux classes existantes.
  </Card>

  <Card title="Trait Conditionable" icon="git-branch" href="/fr/advanced/conditionable">
    Découvrez les chaînes conditionnelles via `when()` / `unless()`.
  </Card>
</Columns>


## Related topics

- [Trait InteractsWithData](/fr/advanced/interacts-with-data.md)
- [Mode client : Talk (synthèse vocale de texte) - VOICEVOX for Laravel](/fr/packages/laravel-voicevox/client-talk.md)
- [Mode natif : Talk (synthèse vocale de texte) - VOICEVOX for Laravel](/fr/packages/laravel-voicevox/native-talk.md)
- [Mode client : Song (synthèse vocale chantée) - VOICEVOX for Laravel](/fr/packages/laravel-voicevox/client-song.md)
- [Trait Dumpable](/fr/advanced/dumpable.md)
