El trait Illuminate\Support\Traits\Conditionable añade a un objeto los métodos when() y unless(). Su característica principal es que permite bifurcar el comportamiento en función de una condición sin romper el encadenamiento de métodos.
El código fuente real se encuentra en src/Illuminate/Conditionable/Traits/Conditionable.php. Se referencia mediante el alias Illuminate\Support\Traits\Conditionable.
Muchas clases de Laravel, como QueryBuilder, EloquentBuilder, Mail o Notification, utilizan este trait.
Cuando el valor del primer argumento es verdadero, se ejecuta la callback del segundo argumento. Cuando es falso, se ejecuta la callback (por defecto) del tercer argumento.
Si la callback devuelve null, se devuelve $this (el objeto que utiliza el trait). Si la callback devuelve algo distinto de null, se devuelve ese valor.
// Se devuelve $this, así que la cadena continúa$query = User::query() ->when($request->has('active'), function ($query) { $query->where('active', true); // devuelve void / null }) ->when($request->filled('name'), function ($query) use ($request) { $query->where('name', 'like', "%{$request->name}%"); }) ->orderBy('created_at', 'desc');
Si lo llamas con un solo argumento, obtienes un proxy que conserva ese valor como condición.
// Un argumento: solo pasa la condición y obtiene un proxy$proxy = collect([1, 2, 3])->when($request->has('filter'));// Con $proxy->methodName() se llama a methodName() solo si la condición es verdadera
tap() y when() se parecen, pero tienen propósitos distintos.
tap()
when()
Objetivo
Efectos colaterales (log, debug)
Bifurcación condicional
Valor de retorno
Siempre $this
$this o el valor devuelto por la callback, según la condición
Condición
No tiene
Sí
// tap: se usa para efectos colaterales. Siempre devuelve $this$user = User::find($id) ->tap(fn ($user) => Log::info("User {$user->id} loaded"));// when: se usa para bifurcaciones condicionales$user = User::query() ->when($isAdmin, fn ($q) => $q->where('role', 'admin')) ->first();
Si solo quieres hacer algo en medio de la cadena por efecto colateral (debug, logging), usa tap(). Si quieres cambiar el comportamiento según una condición, usa when() / unless().