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

> Come implementare in sicurezza il forwarding dei metodi in classi proxy/decorator usando Illuminate\Support\Traits\ForwardsCalls.

## Cos'è il trait ForwardsCalls

`Illuminate\Support\Traits\ForwardsCalls` è un trait che centralizza la delega dei metodi verso un altro oggetto. Nel core di Laravel è utilizzato dai "wrapper" come Eloquent o Mail.

<Info>
  L'implementazione si trova in `src/Illuminate/Support/Traits/ForwardsCalls.php`. Se inoltri un metodo inesistente, rilancia una `BadMethodCallException` formattata con il nome della classe chiamante.
</Info>

```mermaid theme={null}
flowchart LR
  A["La tua classe Proxy"] -->|__call| B["forwardCallTo()"]
  B --> C["Driver / Builder interno"]
  C --> D["Restituisce il risultato"]
  D --> A
```

## API principali

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

Inoltra un metodo così com'è all'oggetto specificato. Tipicamente viene chiamato da `__call()`.

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

Usato in builder e decorator per mantenere la catena. Se il metodo di destinazione restituisce "l'oggetto di destinazione stesso", il valore viene sostituito con "l'oggetto chiamante (`$this`)".

### Combinazione con `__call()` / `__callStatic()`

`ForwardsCalls` non fornisce metodi magic. Sei tu ad implementare `__call()` (e se serve `__callStatic()`) nella tua classe e da lì chiami i metodi `forwardCallTo*`.

## Esempi d'uso reali (interno a Laravel)

<Steps>
  <Step title="I Facade forniscono uno static proxy">
    `Illuminate\Support\Facades\Facade` delega direttamente all'istanza root con `__callStatic()`. Poiché i facade sono chiamate statiche, l'implementazione è un forwarding diretto e non usa `ForwardsCalls`.
  </Step>

  <Step title="L'Eloquent Builder usa forwardCallTo">
    `Illuminate\Database\Eloquent\Builder::__call()` passa i metodi non risolti al Query Builder interno con `forwardCallTo($this->query, ...)` e infine restituisce `$this` per mantenere la fluent chain.
  </Step>

  <Step title="Relation / Mail / Event usano forwardDecoratedCallTo">
    `Illuminate\Database\Eloquent\Relations\Relation`, `Illuminate\Mail\Message` e `Illuminate\Events\NullDispatcher` usano `forwardDecoratedCallTo` per delegare all'oggetto interno preservando la catena dell'API esterna.
  </Step>
</Steps>

## Implementazione base di 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);
    }
}
```

In questa forma, `CourierProxy` espone in modo trasparente l'API pubblica di `CourierDriver`.

## Proxy compatibile con method chaining (`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>
  È più sicuro sfruttare la regola di `forwardDecoratedCallTo` ("se il valore di ritorno è l'oggetto di destinazione, lo sostituisce con `$this`") piuttosto che scrivere manualmente `return $this`.
</Tip>

## Lancio automatico di BadMethodCallException

Se chiami un metodo inesistente, `ForwardsCalls` rilancia una `BadMethodCallException` usando il nome della classe chiamante.

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

In questo modo l'utente identifica subito "quale API esterna è fallita".

## Confronto con Macroable

| Aspetto             | `Macroable`                                    | `ForwardsCalls`                               |
| ------------------- | ---------------------------------------------- | --------------------------------------------- |
| Scopo               | Aggiungere nuovi metodi a una classe esistente | Delegare metodi a un altro oggetto            |
| Ingressi principali | `macro()`, `mixin()`                           | `forwardCallTo()`, `forwardDecoratedCallTo()` |
| Casi adatti         | Estensione di API                              | Proxy / Decorator / Adapter                   |

<Warning>
  Se vuoi "aggiungere metodi", usare `ForwardsCalls` fallirà sempre per i metodi non presenti sul target. Se il tuo obiettivo è estendere un'API, scegli `Macroable`.
</Warning>

## Esempi d'uso nello sviluppo di pacchetti

### 1) Manager che cambia driver

```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 con più backend

Backend diversi come HTTP / Queue / WebSocket possono essere delegati a un'unica API unificata.

### 3) Spy / Stub per i test

Al posto del driver reale puoi iniettare uno spy, lasciando che le chiamate passino attraverso `forwardCallTo` e verificando numero di chiamate e argomenti.

## Pagine correlate

<Columns cols={2}>
  <Card title="Trait Macroable" icon="puzzle-piece" href="/it/advanced/macroable">
    Impara il pattern di estensione per aggiungere metodi a classi esistenti.
  </Card>

  <Card title="Trait Conditionable" icon="git-branch" href="/it/advanced/conditionable">
    Impara a progettare catene condizionali con `when()` / `unless()`.
  </Card>
</Columns>


## Related topics

- [Trait Macroable](/it/advanced/macroable.md)
- [Database seeding](/it/seeding.md)
- [Trait Conditionable](/it/advanced/conditionable.md)
- [Trait Dumpable](/it/advanced/dumpable.md)
- [Classe Fluent](/it/advanced/fluent.md)
