Injections
How Ray.Di initializes your objects
The dependency injection pattern separates behaviour from dependency resolution. Rather than looking up dependencies directly or from factories, the pattern recommends that dependencies are passed in. The process of setting dependencies into an object is called injection.
Constructor Injection
Constructor injection combines instantiation with injection. This constructor should accept class dependencies as parameters. Most constructors will then assign the parameters to properties. You do not need #[Inject]
attribute in constructor.
public function __construct(DbInterface $db)
{
$this->db = $db;
}
Setter Injection
Ray.Di can inject by methods that have the #[Inject]
attribute. Dependencies take the form of parameters, which the injector resolves before invoking the method. Injected methods may have any number of parameters, and the method name does not impact injection.
use Ray\Di\Di\Inject;
#[Inject]
public function setDb(DbInterface $db)
{
$this->db = $db;
}
Property Injection
Ray.Di does not support property injection.
Assisted Injection
Also called method-call injection action injection, or Invocation injection.It is also possible to inject dependencies directly in the invoke method parameter(s). When doing this, add the dependency to the end of the arguments and add #[Assisted]
to the parameter(s). You need null
default for that parameter.
Note that this Assisted Injection is different from the one in Google Guice.
use Ray\Di\Di\Assisted;
public function doSomething(string $id, #[Assisted] DbInterface $db = null)
{
$this->db = $db;
}
You can also provide dependency which depends on other dynamic parameter in method invocation. MethodInvocationProvider
provides MethodInvocation object.
class HorizontalScaleDbProvider implements ProviderInterface
{
public function __construct(
private readonly MethodInvocationProvider $invocationProvider
){}
public function get()
{
$methodInvocation = $this->invocationProvider->get();
[$id] = $methodInvocation->getArguments()->getArrayCopy();
return UserDb::withId($id); // $id for database choice.
}
}
This injection done by AOP is powerful and useful for injecting objects that are only determined at method execution time, as described above. However, this injection is outside the scope of the original IOC and should only be used when really necessary.
Optional Injections
Occasionally it’s convenient to use a dependency when it exists and to fall back
to a default when it doesn’t. Method and field injections may be optional, which
causes Ray.Di to silently ignore them when the dependencies aren’t available. To
use optional injection, apply the #[Inject(optional: true)
attribute:
class PayPalCreditCardProcessor implements CreditCardProcessorInterface
{
private const SANDBOX_API_KEY = "development-use-only";
private string $apiKey = self::SANDBOX_API_KEY;
#[Inject(optional: true)]
public setApiKey(#[Named('paypal-apikey') string $apiKey): void
{
$this->apiKey = $apiKey;
}
}