Guide to Festi DI
Festi DI is Dependency Injection library.
Setup
Composer installation:
"repositories": [
{ "type": "composer", "url": "https://packages.festi.io/" }
]
"require": {
"festi-team/festi-framework-di": "dev-master",
"php": ">=8.0"
}
Basic Dependency Injection
Consider the class:
use core\di\Inject;
class Communication
{
#[Inject]
private ICommunicator $communicator;
public function sendMessage(string $message): void
{
$this->communicator->sendMessage($message);
}
}
The basic entry point:
$injector = new core\di\Injector(new BasicModule());
$instance = $injector->getInstance(Communication::class);
The Module is the basic unit of definition of bindings (Container).
Bindings
With bindings, you define how Festi DI is going to inject dependencies into a class.
A binding is defined in an implementation of core\di\AbstractModule
:
class BasicModule extends core\di\AbstractModule
{
public function configure()
{
$this->bindByClassName(ICommunicator::class, CommunicatorImpl::class);
}
}
This module implementation specifies that an instance of CommunicatorImpl is to be injected wherever a ICommunicator is found with attribute Inject.
Another incarnation of this mechanism is the named binding:
#[Inject(name:'communication')]
private ICommunicator $communicator;
class BasicModule extends core\di\AbstractModule
{
public function configure()
{
$this->bindByName('communication', CommunicatorImpl::class);
}
}
Another approach to constructor-specific binding is the instance binding, where we provide an instance directly in the binding:
class BasicModule extends core\di\AbstractModule
{
public function configure()
{
$this->bindByInstance(ICommunicator::class, new CommunicatorImpl());
}
}
Types of Dependency Injection
Field Injection
#[Inject]
public InterfaceA $a;
#[Inject(ClassA::class)]
protected $b;
#[Inject]
private InterfaceA $c;
#[Inject(name: 'setting_key')]
public string $d;
#[Inject]
public ClassA $f;
Method Injection
Here we use a setter method to achieve the injection:
#[Inject]
public function setA(IMethod $method): void
{
$this->methodA = $method;
}
#[Inject]
protected function setB(#[Inject(IMethod::class)] $method): void
{
$this->methodB = $method;
}
#[Inject]
protected function setC(#[Inject(name: 'setting_key')] string $value): void
{
$this->methodC = $value;
}
Constructor Injection
You can also inject dependencies using a constructor:
public function __construct(
#[Inject] public IConstructItem $a,
#[Inject(IConstructItem::class)] $b,
#[Inject(name: 'setting_key')] $c,
#[Inject] ClassConstructB $d
)
{
}