Le trait Illuminate\Support\Traits\Conditionable ajoute les méthodes when() et unless() à un objet. Sa particularité est de permettre de continuer une chaîne de méthodes tout en dérivant le traitement en fonction d’une condition.
Les sources réelles se trouvent dans src/Illuminate/Conditionable/Traits/Conditionable.php. Elles sont référencées via l’alias Illuminate\Support\Traits\Conditionable.
De nombreuses classes Laravel utilisent ce trait : QueryBuilder, EloquentBuilder, Mail, Notification, etc.
Quand la valeur du premier argument est vraie, le callback du second argument est exécuté. Sinon, le callback (par défaut) du troisième argument est exécuté.
Si la valeur de retour du callback est null, c’est $this (l’objet qui utilise le trait) qui est retourné. Si le callback ne retourne pas null, c’est sa valeur de retour qui est retournée.
// $this est retourné donc la chaîne continue$query = User::query() ->when($request->has('active'), function ($query) { $query->where('active', true); // retourne void / null }) ->when($request->filled('name'), function ($query) use ($request) { $query->where('name', 'like', "%{$request->name}%"); }) ->orderBy('created_at', 'desc');
Si le callback retourne explicitement une valeur, cette valeur est passée au maillon suivant de la chaîne. S’il ne retourne rien (null), $this est retourné.
Avec un seul argument, un proxy contenant cette valeur comme condition est retourné.
// Un argument : passer uniquement la condition pour obtenir un proxy$proxy = collect([1, 2, 3])->when($request->has('filter'));// $proxy->methodName() n'appelle methodName() que si la condition est vraie
when() est également utilisable pour la construction d’e-mails, de notifications et de réponses.
use Illuminate\Mail\Mailable;use Illuminate\Support\Traits\Conditionable;class OrderConfirmation extends Mailable{ public function build(): static { return $this ->subject('Votre commande a bien été reçue') ->view('emails.order.confirmation') ->when($this->order->hasDiscount(), function (Mailable $mail) { $mail->attach(storage_path('discounts/coupon.pdf')); }) ->when(app()->environment('production'), function (Mailable $mail) { $mail->bcc('[email protected]'); }); }}
tap() et when() se ressemblent mais ont des objectifs différents.
tap()
when()
Objectif
Effet de bord (log, debug)
Branchement conditionnel
Valeur de retour
Toujours $this
$this ou la valeur de retour du callback selon la condition
Condition
Aucune
Oui
// tap : à utiliser pour un effet de bord. Retourne toujours $this$user = User::find($id) ->tap(fn ($user) => Log::info("User {$user->id} loaded"));// when : à utiliser pour un branchement conditionnel$user = User::query() ->when($isAdmin, fn ($q) => $q->where('role', 'admin')) ->first();
Si vous voulez juste faire quelque chose au milieu d’une chaîne pour du debug ou un effet de bord, utilisez tap(). Pour changer le traitement selon une condition, utilisez when() / unless().