Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 0
Context
Context provides an expressive way to define any concrete's dependencies.
If you haven't already, refer to this page to learn how to bootstrap and use container.
NOTE: Although Context is a elegant solution to define dependencies, in most cases a simple registration might be sufficient. It is recommended to use this feature only when some not-so-simple logic is required to resolve the concrete's dependency.
Defining primitive type's value based on Parameter Name:
class CurrentUser {
publicfunction__construct(privatestring$id) {}
publicfunctiongetId(): string {
return$this->id;
}
}
$app->when(CurrentUser::class)
->needs('$id') // Requires "$" to imply it is a parameter name (and must not be omitted).
->give(staticfn() => 5);
$app->get(CurrentUser::class)->getId() === 5; // true.Defining classes or interfaces based on Parameter TypeHint (doesn't support intersection/union types):
interface PaymentProcessor {
publicfunctionsetAmount(string$amount): self;
publicfunctionprocess(): void;
}
class Stripe implements PaymentProcessor {
privatestring$amount;
publicfunctionsetAmount(string$amount): self {
$this->amount = $amount;
return$this;
}
publicfunctionprocess(): void {
// ...Processes using $this->amount.
}
}
class PaymentService {
publicfunction__construct(privatePaymentProcessor$paymentProcessor) {}
publicfunctionprocess(): void {
$this->paymentProcessor->process();
}
}
$app->when(PaymentService::class)
->needs(PaymentProcessor::class)
->give(Stripe::class);
// When some initialization is needed before resolving the dependency.$app->when(PaymentService::class)
->needs(PaymentProcessor::class)
->give(
staticfn(Container$c): Stripe => $c->get(Stripe::class)->setAmount(100)
);
// When concrete is aliased, alias can be used when defining context.$app->setAlias(PaymentService::class, 'processPayment');
$app->when('processPayment')
->needs(PaymentProcessor::class)
->give(Stripe::class);When more than one concrete requires same dependency.
useWeakMap;
useArrayObject;
useArrayAccess;
class FirstClass {
publicfunction__construct(publicArrayAccess$stack = newWeakMap()) {}
}
class SecondClass {
publicfunction__construct(publicArrayAccess$stack = newWeakMap()) {}
}
$app->when([FirstClass::class, SecondClass::class])
->needs(ArrayAccess::class)
->give(ArrayObject::class);
$app->get(FirstClass::class)->stackinstanceof ArrayObject; // true.$app->get(SecondClass::class)->stackinstanceof ArrayObject; // true.When method call context needs to be defined.
useArrayObject;
useArrayAccess;
functioncurrentUserDetails(): ArrayAccess {
$fromDatabase = (object) // ...Typecast current user's fetched data from database.
return newArrayObject([
'first_name' => $fromDatabase->firstName,
'last_name' => $fromDatabase->lastName,
]);
}
class Controller {
publicfunctionrenderCurrentUser(ArrayAccess$details): void {
echo"First Name: {$details['first_name']}";
echo"Last Name: {$details['last_name']}";
}
}
$app->when(Controller::class . '::renderCurrentUser')
->needs(ArrayAccess::class)
->give(currentUserDetails(...));
$app->call(Controller::class, methodName: 'renderCurrentUser'); // Renders first name & last name.If an instantiated controller's method call context needs to be defined. This will limit the context's scope to the instantiated object's method call only. Otherwise, context of non-instantiated method call will be used (if it is defined).
Continuing from Case 2:
$controller = newController();
$app->when($controller->renderCurrentUser(...))
->needs(ArrayAccess::class)
->give(currentUserDetails(...));
$app->call($controller->renderCurrentUser(...)); // Renders first name & last name.