Zum Hauptinhalt springen

Was ist der ForwardsCalls-Trait?

Illuminate\Support\Traits\ForwardsCalls ist ein Trait, der die Delegation von Methoden an ein anderes Objekt vereinheitlicht. Im Laravel-Kern wird er in „Wrapper-Objekten” wie Eloquent oder Mail eingesetzt.
Die Implementierung befindet sich unter src/Illuminate/Support/Traits/ForwardsCalls.php. Beim Weiterleiten einer nicht existierenden Methode wird eine BadMethodCallException mit dem aufrufenden Klassennamen erneut geworfen.

Kern-API

forwardCallTo($object, $method, $parameters)

Leitet die Methode unverändert an das angegebene Objekt weiter. Der typische Aufrufort ist __call().

forwardDecoratedCallTo($object, $method, $parameters)

Nützlich, wenn Sie in einem Builder oder Decorator die Chain aufrechterhalten wollen. Gibt die weitergeleitete Methode „das Zielobjekt selbst” zurück, wird stattdessen das „aufrufende Objekt ($this)” zurückgegeben.

Kombination mit __call() / __callStatic()

ForwardsCalls liefert keine Magic Methods. Sie implementieren __call() (bei Bedarf auch __callStatic()) in Ihrer Klasse und rufen dort die forwardCallTo-Methoden auf.

Reale Anwendungsbeispiele (Laravel-intern)

1

Facade stellt einen Static Proxy bereit

Illuminate\Support\Facades\Facade delegiert in __callStatic() direkt an die Root-Instanz. Da Facades statisch aufgerufen werden, ist das keine Verwendung von ForwardsCalls, sondern eine direkte Weiterleitung.
2

Der Eloquent Builder nutzt forwardCallTo

Illuminate\Database\Eloquent\Builder::__call() reicht unbekannte Methoden über forwardCallTo($this->query, ...) an den internen Query Builder weiter und gibt am Ende $this zurück, um die Fluent Chain zu erhalten.
3

Relation / Mail / Event verwenden forwardDecoratedCallTo

In Illuminate\Database\Eloquent\Relations\Relation, Illuminate\Mail\Message und Illuminate\Events\NullDispatcher kommt forwardDecoratedCallTo zum Einsatz — es delegiert an das interne Objekt und bewahrt gleichzeitig die Chain der äußeren API.

Einfache Proxy-Implementierung (forwardCallTo)

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 dieser Form legt CourierProxy die public API des CourierDriver transparent offen.

Method-Chain-fähiger Proxy (forwardDecoratedCallTo)

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();
    }
}
$users = (new QueryProxy(User::query()))
    ->where('active', true)
    ->orderByDesc('created_at')
    ->limit(10)
    ->get();
Statt jedes Mal manuell return $this zu schreiben, ist es sicherer, die Regel „Wenn der Rückgabewert das Ziel-Objekt selbst ist, durch $this ersetzen” von forwardDecoratedCallTo zu nutzen.

Automatisches Werfen einer BadMethodCallException

Wird eine nicht existierende Methode aufgerufen, wirft ForwardsCalls eine neue BadMethodCallException mit dem aufrufenden Klassennamen.
try {
    (new CourierProxy($driver))->missingMethod();
} catch (\BadMethodCallException $e) {
    // Beispiel: Call to undefined method App\Services\CourierProxy::missingMethod()
    report($e);
}
So kann der Nutzer sofort erkennen, „an welcher äußeren API der Fehler auftrat”.

Vergleich mit Macroable

AspektMacroableForwardsCalls
ZweckNeue Methoden an eine bestehende Klasse anfügenMethoden an ein anderes Objekt delegieren
Haupteinstiegmacro(), mixin()forwardCallTo(), forwardDecoratedCallTo()
Geeigneter AnwendungsfallAPI-ErweiterungProxy / Decorator / Adapter
Wenn Sie „Methoden ergänzen” wollen und stattdessen ForwardsCalls verwenden, schlagen Aufrufe von Methoden, die das Delegationsziel nicht kennt, immer fehl. Wählen Sie für API-Erweiterungen Macroable.

Anwendungsbeispiele in der Paketentwicklung

1) Manager, der Treiber umschaltet

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 mit mehreren Backends

Unterschiedliche Backends wie HTTP, Queue oder WebSocket lassen sich hinter einer einheitlichen API bündeln.

3) Spy / Stub für Tests

Statt eines echten Drivers injizieren Sie einen Spy — die Aufrufe werden per forwardCallTo unverändert durchgereicht, und Sie können Anzahl sowie Argumente der Aufrufe prüfen.

Verwandte Seiten

Macroable-Trait

Lernen Sie das Erweiterungsmuster kennen, um bestehenden Klassen neue Methoden hinzuzufügen.

Conditionable-Trait

Lernen Sie den Entwurf von Bedingungs-Chains mit when() / unless() kennen.
Zuletzt geändert am 13. Juli 2026