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

# Trait ForwardsCalls

> Implémentez le transfert de méthodes de proxies/décorateurs en toute sécurité avec Illuminate\Support\Traits\ForwardsCalls.

## Qu'est-ce que le trait ForwardsCalls

`Illuminate\Support\Traits\ForwardsCalls` est un trait qui mutualise la délégation d'appels de méthodes vers un autre objet. Dans le cœur de Laravel, il est utilisé par les « objets wrappers » comme Eloquent ou Mail.

<Info>
  L'implémentation se trouve dans `src/Illuminate/Support/Traits/ForwardsCalls.php`. Lorsqu'une méthode inexistante est transférée, l'exception `BadMethodCallException` est reformatée pour inclure le nom de la classe appelante et relancée.
</Info>

```mermaid theme={null}
flowchart LR
  A["Votre classe Proxy"] -->|__call| B["forwardCallTo()"]
  B --> C["Driver / Builder interne"]
  C --> D["Retourne le résultat"]
  D --> A
```

## API de base

### `forwardCallTo($object, $method, $parameters)`

Transfère directement une méthode à l'objet spécifié. Typiquement appelé depuis `__call()`.

### `forwardDecoratedCallTo($object, $method, $parameters)`

À utiliser quand un Builder ou un Decorator veut préserver le chaînage. Si la valeur de retour de la méthode ciblée est « l'objet de destination lui-même », elle est remplacée par « l'objet appelant (`$this`) » avant d'être retournée.

### Combinaison avec `__call()` / `__callStatic()`

`ForwardsCalls` ne fournit pas de méthodes magiques. Vous implémentez `__call()` (et si besoin `__callStatic()`) dans votre classe et vous y appelez les méthodes `forwardCallTo...`.

## Exemples d'utilisation réels (interne à Laravel)

<Steps>
  <Step title="Les Facades fournissent un static proxy">
    `Illuminate\Support\Facades\Facade` délègue directement à l'instance racine via `__callStatic()`. Les facades étant des appels statiques, elles utilisent une délégation directe et non `ForwardsCalls`.
  </Step>

  <Step title="Eloquent Builder utilise forwardCallTo">
    `Illuminate\Database\Eloquent\Builder::__call()` transmet les méthodes non résolues au Query Builder interne via `forwardCallTo($this->query, ...)`, puis retourne `$this` en fin de traitement pour préserver la chaîne fluide.
  </Step>

  <Step title="Relation / Mail / Event utilisent forwardDecoratedCallTo">
    `Illuminate\Database\Eloquent\Relations\Relation`, `Illuminate\Mail\Message` et `Illuminate\Events\NullDispatcher` utilisent `forwardDecoratedCallTo` : ils délèguent à l'objet interne tout en préservant le chaînage de l'API externe.
  </Step>
</Steps>

## Implémentation de base d'un proxy (`forwardCallTo`)

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

class CourierProxy
{
    use ForwardsCalls;

    public function __construct(
        protected CourierDriver $driver
    ) {}

    public function __call(string $method, array $parameters): mixed
    {
        return $this->forwardCallTo($this->driver, $method, $parameters);
    }
}
```

Ainsi, `CourierProxy` expose de façon transparente l'API publique de `CourierDriver`.

## Proxy compatible chaînage (`forwardDecoratedCallTo`)

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

class QueryProxy
{
    use ForwardsCalls;

    public function __construct(
        protected Builder $query
    ) {}

    public function __call(string $method, array $parameters): static
    {
        $this->forwardDecoratedCallTo($this->query, $method, $parameters);

        return $this;
    }

    public function get(): \Illuminate\Support\Collection
    {
        return $this->query->get();
    }
}
```

```php theme={null}
$users = (new QueryProxy(User::query()))
    ->where('active', true)
    ->orderByDesc('created_at')
    ->limit(10)
    ->get();
```

<Tip>
  Plutôt que d'écrire manuellement `return $this`, utilisez la règle de `forwardDecoratedCallTo` (« si la valeur de retour est l'objet de destination lui-même, le remplacer par `$this` »), c'est plus sûr.
</Tip>

## Lancement automatique de BadMethodCallException

Lorsqu'une méthode inexistante est appelée, `ForwardsCalls` relance une `BadMethodCallException` avec le nom de la classe appelante.

```php theme={null}
try {
    (new CourierProxy($driver))->missingMethod();
} catch (\BadMethodCallException $e) {
    // Ex. : Call to undefined method App\Services\CourierProxy::missingMethod()
    report($e);
}
```

L'utilisateur peut ainsi identifier immédiatement « dans quelle API externe l'échec est survenu ».

## Comparaison avec Macroable

| Aspect                     | `Macroable`                                          | `ForwardsCalls`                               |
| -------------------------- | ---------------------------------------------------- | --------------------------------------------- |
| Objectif                   | Ajouter de nouvelles méthodes à une classe existante | Déléguer des méthodes à un autre objet        |
| Points d'entrée principaux | `macro()`, `mixin()`                                 | `forwardCallTo()`, `forwardDecoratedCallTo()` |
| Cas approprié              | Extension d'API                                      | Proxy / Decorator / Adapter                   |

<Warning>
  Utiliser `ForwardsCalls` pour « ajouter des méthodes » aboutit à des échecs systématiques pour les méthodes que la cible ne possède pas. Si votre but est d'étendre une API, choisissez `Macroable`.
</Warning>

## Exemples d'utilisation dans le développement de packages

### 1) Manager qui bascule entre plusieurs Drivers

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

class SmsManager
{
    use ForwardsCalls;

    public function __construct(
        protected SmsDriver $driver
    ) {}

    public function via(string $name): static
    {
        $this->driver = app(SmsDriverFactory::class)->make($name);

        return $this;
    }

    public function __call(string $method, array $parameters): mixed
    {
        return $this->forwardCallTo($this->driver, $method, $parameters);
    }
}
```

### 2) Adapter à plusieurs backends

Différents backends (HTTP, Queue, WebSocket, etc.) peuvent être délégués à travers une API unifiée.

### 3) Spy / Stub pour les tests

À la place du driver réel, injectez un Spy et faites transiter les appels via `forwardCallTo` tout en vérifiant le nombre d'appels et les arguments.

## Pages associées

<Columns cols={2}>
  <Card title="Trait Macroable" icon="puzzle-piece" href="/fr/advanced/macroable">
    Découvrez le pattern d'extension qui ajoute de nouvelles méthodes à une classe existante.
  </Card>

  <Card title="Trait Conditionable" icon="git-branch" href="/fr/advanced/conditionable">
    Apprenez à concevoir des chaînes conditionnelles avec `when()` / `unless()`.
  </Card>
</Columns>


## Related topics

- [Trait Macroable](/fr/advanced/macroable.md)
- [Seeding de base de données](/fr/seeding.md)
- [Trait Conditionable](/fr/advanced/conditionable.md)
- [Trait Dumpable](/fr/advanced/dumpable.md)
- [Classe Fluent](/fr/advanced/fluent.md)
