Skip to main content

What is the ForwardsCalls trait?

Illuminate\Support\Traits\ForwardsCalls standardizes method delegation from one object to another. Laravel uses it in wrapper-style classes across Eloquent, Mail, and Events.
The implementation is in src/Illuminate/Support/Traits/ForwardsCalls.php. When a forwarded method does not exist, it rethrows a normalized BadMethodCallException with the caller class name.

Core API

forwardCallTo($object, $method, $parameters)

Forwards a method call directly to another object. You usually call this from __call().

forwardDecoratedCallTo($object, $method, $parameters)

Use this for fluent decorators/builders. If the forwarded method returns the inner object itself, this method returns the outer object ($this) instead, so your chain stays on the wrapper.

Combining with __call() and __callStatic()

ForwardsCalls does not implement magic methods for you. You implement __call() (and optionally __callStatic()) in your class, then call forwardCallTo methods inside them.

Real Laravel usage

1

Facade provides static proxying

Illuminate\Support\Facades\Facade forwards in __callStatic() directly to the facade root instance. Because Facade is static proxying, it uses direct delegation rather than ForwardsCalls.
2

Eloquent Builder uses forwardCallTo

Illuminate\Database\Eloquent\Builder::__call() forwards unresolved methods to the inner query builder with forwardCallTo($this->query, ...), then returns $this to keep fluent chains.
3

Relation / Mail / Events use forwardDecoratedCallTo

Illuminate\Database\Eloquent\Relations\Relation, Illuminate\Mail\Message, and Illuminate\Events\NullDispatcher use forwardDecoratedCallTo to preserve the outer API while delegating work.

Basic proxy implementation (forwardCallTo)

This pattern exposes the inner driver’s public API through your wrapper class.

Fluent proxy implementation (forwardDecoratedCallTo)

Prefer forwardDecoratedCallTo over manual return $this glue logic. It handles the “inner object returned itself” case consistently.

Automatic BadMethodCallException

When a method is missing on the forwarded object, ForwardsCalls rethrows a BadMethodCallException using the wrapper class name.
This keeps error messages aligned with the API your users call.

Comparing with Macroable

If your goal is “add new methods”, ForwardsCalls is the wrong tool. Calls still fail when the inner object does not implement that method. Use Macroable for true API extension.

Package development patterns

1) Driver-switching manager

2) Adapter for multiple backends

Use one stable API while switching among HTTP, queue, or WebSocket backends internally.

3) Test spy/stub wrappers

Inject a spy driver and route calls through forwardCallTo so you can assert call count and arguments while keeping production-like behavior.

The Macroable trait

Learn the API extension pattern for adding methods to existing classes.

The Conditionable trait

Learn conditional fluent chains with when() and unless().
Last modified on July 13, 2026