Skip to main content

Contextual Bindings

Overview

Contextual bindings let you override a dependency for a specific consumer class. This means you can tailor dependency resolution on a per-class basis—ensuring that a given consumer receives a different implementation of an abstract dependency than the one provided globally. This feature is especially useful when you want to replace the default implementation in a particular context without affecting other parts of your application.


How Contextual Bindings Work

Contextual bindings are managed using a series of builder methods that allow you to define the override in three steps:

when() Method

This method accepts the concrete (consumer) class name and returns a builder instance that sets the context for the binding override.

ParameterTypeRequiredDescription
$concretestringYesThe concrete class name for which you want to override dependencies.

needs() Method

Once the context is set via when(), you call needs() on the builder. This method accepts the abstract dependency identifier (typically an interface or abstract class) that you wish to override and returns another builder instance.

ParameterTypeRequiredDescription
$abstractstringYesThe identifier (usually an interface or abstract class) whose binding should be overridden.

give() Method

Finally, call give() on the resulting builder to specify the concrete implementation to use for that dependency in the given context.

ParameterTypeRequiredDescription
$implementationstringYesThe concrete implementation (class name) that should be injected for the specified dependency.

Internally, contextual bindings are stored in an associative array that maps each consumer class to its specific dependency overrides.


Example Usage

Below is an example demonstrating how to use contextual bindings in the container:

$container = new Container();

// Global binding for LoggerInterface:
$container->bind(LoggerInterface::class, DefaultLogger::class);

// When constructing SomeController, use SpecialLogger instead of DefaultLogger:
$container->when(SomeController::class)
->needs(LoggerInterface::class)
->give(SpecialLogger::class);

// Resolving SomeController now injects SpecialLogger for the LoggerInterface dependency.
$controller = $container->get(SomeController::class);

In this example:

  • The container globally binds LoggerInterface to DefaultLogger.
  • Using contextual bindings, when SomeController is resolved, it receives SpecialLogger instead of the global default.
  • This override is limited only to SomeController, leaving other consumers to use the default binding.

Summary

Contextual bindings provide a flexible mechanism to override dependencies for specific consumer classes without altering global service configurations. By using the when(), needs(), and give() methods, you can fine-tune dependency injection for different parts of your application, making your codebase more adaptable and maintainable.