什么是 ForwardsCalls trait
Illuminate\Support\Traits\ForwardsCalls 是用于统一某个对象方法委托的 trait。在 Laravel 本体中,它被 Eloquent、Mail 等「包装对象」使用。
实现位于
src/Illuminate/Support/Traits/ForwardsCalls.php。当转发到不存在的方法时,会重新抛出一个包含调用方类名的 BadMethodCallException。核心 API
forwardCallTo($object, $method, $parameters)
将方法原样转发到指定对象。通常从 __call() 中调用。
forwardDecoratedCallTo($object, $method, $parameters)
在 Builder 或 Decorator 中希望保持链式调用时使用。若转发目标方法的返回值是「目标对象自身」,则替换为「调用方对象($this)」返回。
与 __call() / __callStatic() 的组合
ForwardsCalls 本身不提供魔术方法。你需要在自己的类中实现 __call()(必要时还有 __callStatic()),并在其中调用 forwardCallTo 系列方法。
实际使用示例(Laravel 内部)
Facade 提供静态代理
Illuminate\Support\Facades\Facade 通过 __callStatic() 直接委托到 root instance。Facade 是静态调用,因此并没有使用 ForwardsCalls,而是直接转发实现。Eloquent Builder 使用 forwardCallTo
Illuminate\Database\Eloquent\Builder::__call() 会通过 forwardCallTo($this->query, ...) 将未解析的方法转发给内部 Query Builder,最后返回 $this 以保持链式调用。基础 Proxy 实现(forwardCallTo)
CourierProxy 就能透明地对外暴露 CourierDriver 的 public API。
支持链式调用的 Proxy(forwardDecoratedCallTo)
自动抛出 BadMethodCallException
调用不存在的方法时,ForwardsCalls 会用调用方类名重新抛出 BadMethodCallException。
与 Macroable 的对比
| 视角 | Macroable | ForwardsCalls |
|---|---|---|
| 目的 | 向既有类新增方法 | 将方法委托给另一个对象 |
| 主要入口 | macro()、mixin() | forwardCallTo()、forwardDecoratedCallTo() |
| 适用场景 | 扩展 API | Proxy / Decorator / Adapter |
包开发中的应用示例
1) 切换 Driver 的 Manager
2) 支持多种后端的 Adapter
可以把 HTTP / Queue / WebSocket 等不同后端统一到同一个 API 后再委托。3) 用于测试的 Spy / Stub
用 Spy 代替真实 Driver 注入,调用通过forwardCallTo 原样转发,从而校验调用次数与参数。
相关页面
Macroable trait
学习向既有类添加新方法的扩展模式。
Conditionable trait
学习基于
when() / unless() 的条件分支链式设计。