跳转到主要内容

什么是 Conditionable trait

Illuminate\Support\Traits\Conditionable trait 为对象添加了 when()unless() 方法。它的特点是可以在方法链中按条件分支执行处理。
实际源码位于 src/Illuminate/Conditionable/Traits/Conditionable.php,通过别名 Illuminate\Support\Traits\Conditionable 引用。
QueryBuilder、EloquentBuilder、Mail、Notification 等 Laravel 中许多类都使用了该 trait。

基本用法

when() — 条件为真时执行

当第 1 个参数的值为真时,第 2 个参数的回调会被执行;为假时,则执行第 3 个参数的回调(默认回调)。

unless() — 条件为假时执行

unless()when() 的相反版本。条件为假时执行回调。

方法链得以延续的原因

当回调返回值为 null 时,将返回 $this(使用该 trait 的对象)。当回调返回非 null 值时,就使用该返回值。
源码中的实现如下:
如果回调返回了明确的值,该值会传递给链的下一步;否则(返回 null)返回的是 $this

无参数调用 — HigherOrderWhenProxy

不传参数调用 when() 时会返回 HigherOrderWhenProxy。这样可以稍后再设置条件。
传入 1 个参数调用时,会返回一个持有该值作为条件的代理。

传入闭包作为值

若第 1 个参数是闭包,则以该闭包的返回值作为条件。
由此可以将条件的求值逻辑拆分到回调中。

在 QueryBuilder 中的典型模式

使用 when() 构建动态查询是最常见的用途。

在自定义类中使用 Conditionable

只需 use 该 trait,就能获得 when() / unless() 能力。

在 Mail、Notification、Response 中的应用

when() 也可用于邮件、通知和响应的构建。

与 tap() 的区别

tap()when() 看似相似,但目的不同。
只是想在链式调用中做一些调试或副作用的话,使用 tap()。要根据条件切换处理逻辑,则使用 when() / unless()

下一步

集合的高阶消息

了解 $collection->map->method() 这类语法的机制与实用用法。
最后修改于 2026年7月18日