Dependency injection¶
Note
For performance reasons, dependency injection is not used in the core part of the framework.
Dependency Injection (DI) is a design pattern used to implement IoC. |br| It allows the creation of dependent objects outside of a class and provides those objects to a class through different ways. Using DI, we move the creation and binding of the dependent objects outside of the class that depends on it.
Note
- Ubiquity only supports 2 types of injections, so as not to require introspection at execution:
- property injection
- setter injection
Only controllers support dependency injection.
Service autowiring¶
Service creation¶
Create a service
1 2 3 4 5 6 7 8 9 10 11 | namespace services;
class Service{
public function __construct($ctrl){
echo 'Service instanciation in '.get_class($ctrl);
}
public function do($someThink=""){
echo 'do '.$someThink ."in service";
}
}
|
Autowiring in Controller¶
Create a controller that requires the service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | namespace controllers;
/**
* Controller Client
**/
class ClientController extends ControllerBase{
/**
* @autowired
* @var services\Service
*/
private $service;
public function index(){}
/**
* @param \services\Service $service
*/
public function setService($service) {
$this->service = $service;
}
}
|
In the above example, Ubiquity looks for and injects $service when ClientController is created.
- The @autowired annotation requires that:
- the type to be instantiated is declared with the @var annotation
- $service property has a setter, or whether declared public
As the annotations are never read at runtime, it is necessary to generate the cache of the controllers:
Ubiquity init-cache -t=controllers
It remains to check that the service is injected by going to the address /ClientController
.
Service injection¶
Service¶
Let’s now create a second service, requiring a special initialization.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class ServiceWithInit{
private $init;
public function init(){
$this->init=true;
}
public function do(){
if($this->init){
echo 'init well initialized!';
}else{
echo 'Service not initialized';
}
}
}
|
Injection in controller¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | namespace controllers;
/**
* Controller Client
**/
class ClientController extends ControllerBase{
/**
* @autowired
* @var \services\Service
*/
private $service;
/**
* @injected
*/
private $serviceToInit;
public function index(){
$this->serviceToInit->do();
}
/**
* @param \services\Service $service
*/
public function setService($service) {
$this->service = $service;
}
/**
* @param mixed $serviceToInit
*/
public function setServiceToInit($serviceToInit) {
$this->serviceToInit = $serviceToInit;
}
}
|
Di declaration¶
In app/config/config.php
, create a new key for serviceToInit property to inject in di part.
"di"=>["ClientController.serviceToInit"=>function(){
$service=new \services\ServiceWithInit();
$service->init();
}
]
generate the cache of the controllers:
Ubiquity init-cache -t=controllers
Check that the service is injected by going to the address /ClientController
.
Note
If the same service is to be used in several controllers, use the wildcard notation :
"di"=>["*.serviceToInit"=>function(){
$service=new \services\ServiceWithInit();
$service->init();
}
]
Injection with a qualifier name¶
If the name of the service to be injected is different from the key of the di array, it is possible to use the name attribute of the @injected annotation
In app/config/config.php
, create a new key for serviceToInit property to inject in di part.
"di"=>["*.service"=>function(){
$service=new \services\ServiceWithInit();
$service->init();
}
]
/**
* @injected("service")
*/
private $serviceToInit;
Service injection at runtime¶
It is possible to inject services at runtime, without these having been previously declared in the controller classes.
1 2 3 4 5 6 7 | namespace services;
class RuntimeService{
public function __construct($ctrl){
echo 'Service instanciation in '.get_class($ctrl);
}
}
|
In app/config/config.php
, create the @exec key in di part.
"di"=>["@exec"=>"rService"=>function($ctrl){
return new \services\RuntimeService($ctrl);
$service->init();
}
]
With this declaration, the $rService member, instance of RuntimeService, is injected into all the controllers. [br| It is then advisable to use the documentation to declare $rService in the controllers that use it (to get the code completion on $rService in your IDE).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | namespace controllers;
/**
* Controller Client
* property services\RuntimeService $rService
**/
class MyController extends ControllerBase{
public function index(){
$this->rService->do();
}
}
<br />
|