Contextual Binding

Contextual Binding, Tagging, and Contextual Attributes

The till in the physical shop reuses the checkout but takes cash. Contextual binding gives one consumer its own implementation of an interface, and tagging names a group of bindings:

Inside AppServiceProvider::register()PHP
$this->app->when(TillCheckout::class)
    ->needs(PaymentGateway::class)
    ->give(CashDrawer::class);
$this->app->tag([SalesReport::class, LowStockReport::class], 'reports');

The trace in The Service Container showed TillCheckout, a subclass of Checkout, receiving CashDrawer; needs('$min')->give(3) would pass a scalar by name.

Contextual attributes declare the same on the parameter. LowStockReport takes #[Config('shop.low_stock', 5)] private int $threshold, and DailyDigest takes #[Tag('reports')] private iterable $reports and prints one line per report:

Resolving the digestShell
echo app(App\Reports\DailyDigest::class)->render(), "\n";
Output
- Sales: 0 orders, $0.00
- Below 5: BK-102, BK-103, BK-105

The tagged set arrives as a lazy RewindableGenerator, so each report is built only when the loop reaches it. The other built-in attributes in Illuminate\Container\Attributes are Auth, Cache, DB, Log, Storage, Context, Give, RouteParameter, RequestAttribute and CurrentUser; your own implements ContextualAttribute with a static resolve().