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
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.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.Basic proxy implementation (forwardCallTo)
Fluent proxy implementation (forwardDecoratedCallTo)
Automatic BadMethodCallException
When a method is missing on the forwarded object, ForwardsCalls rethrows a BadMethodCallException using the wrapper class name.
Comparing with Macroable
| Topic | Macroable | ForwardsCalls |
|---|---|---|
| Goal | Add new methods to a class | Delegate calls to another object |
| Main entry points | macro(), mixin() | forwardCallTo(), forwardDecoratedCallTo() |
| Best fit | API extension | Proxy / Decorator / Adapter |
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 throughforwardCallTo so you can assert call count and arguments while keeping production-like behavior.
Related pages
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().