News

BindWhen Container Attribute in Laravel 13.22

Published
BindWhen Container Attribute in Laravel 13.22 image

Release updates

Never miss a Laravel release

Get an email whenever a new Laravel release lands.

Laravel 13.22 adds a #[BindWhen] attribute for conditional container bindings, a Validator::fakeDnsLookups() method for testing DNS-backed validation rules, #[Delay] attribute support for batched and bulk-dispatched jobs, and comma-separated queue names in the queue:clear command. The Laravel team released v13.22.0 on July 24, 2026.

  • #[BindWhen] attribute for conditional container bindings
  • Fake DNS lookups in the active_url and email:dns validation rules
  • #[Delay] attribute support for Bus::batch() and Queue::bulk()
  • Multi-queue support in queue:clear
  • A macroable rate limiter, restored HTTP fake stream bodies, and assorted fixes

What's New

#[BindWhen] Attribute for Conditional Bindings

The #[Bind] attribute ties an interface to a concrete implementation, but its only conditional hook is the environments argument. The new #[BindWhen] attribute accepts a closure that receives the container, so a binding can depend on configuration, feature flags, or anything else resolvable at runtime:

use Illuminate\Container\Attributes\Bind;
use Illuminate\Container\Attributes\BindWhen;
 
#[BindWhen(BetaPaymentGateway::class, static function ($container) {
return $container->make('config')->get('features.payments.beta');
})]
#[Bind(FakePaymentGateway::class, environments: ['local', 'testing'])]
#[Bind(StripePaymentGateway::class)]
interface PaymentGatewayInterface {}

The attribute is repeatable and conditions are evaluated in declaration order, so conditional bindings can sit ahead of a default #[Bind] fallback. Note that closures in attribute arguments are a PHP 8.5 language feature. Contributed by @ziadoz in #60862.

Faking DNS Lookups in Validation

The active_url rule and the dns option on the email rule perform real DNS queries, which makes any test that exercises them dependent on the network and prone to random failures. A new fakeDnsLookups() method skips the lookup while keeping the rest of the validation intact:

use Illuminate\Support\Facades\Validator;
 
protected function setUp(): void
{
parent::setUp();
 
Validator::fakeDnsLookups();
}

Malformed URLs and email addresses still fail validation; only the network call is bypassed. Passing false turns the fake back off. Contributed by @SjorsO in #60879.

#[Delay] Attribute Support for Batches and Bulk Dispatch

Jobs that declare their delay with the #[Delay] attribute were delayed when dispatched individually, but Bus::batch() and Queue::bulk() only honored the $delay property and silently ignored the attribute. The queue drivers now check both, so the attribute behaves consistently across every dispatch path:

use Illuminate\Queue\Attributes\Delay;
 
#[Delay(15)]
class ProcessPodcast implements ShouldQueue
{
use Queueable;
}
 
Bus::batch([new ProcessPodcast])->dispatch();

Contributed by @jackbayliss in #60766.

Multi-Queue Support in queue:clear

The queue:clear command now accepts comma-separated queue names, matching the convention already used by queue:work and queue:listen:

php artisan queue:clear redis --queue=high,low,emails

Whitespace is trimmed and duplicate names are removed before clearing. Contributed by @miladshakerdn in #60873.

Other Fixes and Improvements

  • The RateLimiter class is now macroable (#60869), and the QueueFake implements creationTimeOfOldestPendingJob() so code that inspects queue age runs under Queue::fake() (#60730)
  • HTTP fake responses accept PSR-7 StreamInterface instances and PHP stream resources again, fixing a regression introduced by earlier body validation (#60834)
  • The JobReleasedAfterException event now carries the exception that caused the release (#60823)
  • Fixed the queue name parameter in Mailer::later() (#60865) and expiration handling in Cache::touch() (#60878)
  • Restored iterable support in Arr::every() and Arr::some() (#60876) and in Arr::last() (#60881)
  • HTTP testing credentials are marked as sensitive parameters so they stay out of stack traces (#60880)
  • Str::ucfirst() and Str::lcfirst() now use the native multibyte functions added in PHP 8.4 (#60864), and class attribute resolution now checks attributes declared on traits (#60566)

Upgrade Notes

No breaking changes are expected for typical applications. Keep in mind that #[BindWhen] relies on closures in attribute arguments, which requires PHP 8.5. Review the changelog for PR-by-PR details when upgrading.

References

Paul Redmond photo

Staff writer at Laravel News. Full stack web developer and author.

Sponsored

acquaintsoft logo
Acquaint Softtech

Hire Laravel developers with AI expertise at $20/hr. Get started in 48 hours.

Visit Acquaint Softtech

The latest

View all →
Laravel Truss: Live Interactive Database ER Diagrams image

Laravel Truss: Live Interactive Database ER Diagrams

Read article
Laravel artisan dev: Run Server, Queue, Logs, and Vite image

Laravel artisan dev: Run Server, Queue, Logs, and Vite

Read article
Validate and Convert HEIC Images in Laravel image

Validate and Convert HEIC Images in Laravel

Read article
Saga Lara Flow: Durable Workflows and Compensating Transactions on Laravel Queues image

Saga Lara Flow: Durable Workflows and Compensating Transactions on Laravel Queues

Read article
Reject Unexpected Array Keys with Laravel Validation image

Reject Unexpected Array Keys with Laravel Validation

Read article
Major performance improvements & security patches for Filament v4.12 and v5.7! image

Major performance improvements & security patches for Filament v4.12 and v5.7!

Read article