Injection de dépendances
Note
Pour des raisons de performances, l’injection de dépendances n’est pas utilisée dans le cœur du framework.
L’injection de dépendances (DI) est un modèle de conception utilisé pour mettre en œuvre l’IoC.
Il permet de créer des objets dépendants en dehors d’une classe et de fournir ces objets à une classe de différentes manières. En utilisant l’injection de dépendances, nous déplaçons la création et la liaison des objets dépendants en dehors de la classe qui en dépend.
Note
Ubiquity ne supporte que l’injection de propriétés, afin de ne pas recourir à l’introspection à l’exécution.
Seuls les contrôleurs supportent l’injection de dépendances.
Autowiring de service
Création de service
Créer un service
1namespace services;
2
3 class Service{
4 public function __construct($ctrl){
5 echo 'Service instanciation in '.get_class($ctrl);
6 }
7
8 public function do($someThink=""){
9 echo 'do '.$someThink ."in service";
10 }
11 }
Autowiring dans un contrôleur
Créer un contrôleur utilisant le service
1 namespace controllers;
2
3 /**
4 * Controller Client
5 **/
6 class ClientController extends ControllerBase{
7
8 /**
9 * @autowired
10 * @var services\Service
11 */
12 private $service;
13
14 public function index(){}
15
16 /**
17 * @param \services\Service $service
18 */
19 public function setService($service) {
20 $this->service = $service;
21 }
22 }
Dans l’exemple ci-dessus, Ubiquity recherche et injecte $service lorsque ClientController est créé.
- L’annotation @autowired nécessite que :
Le type à instancier soit déclaré avec l’annotation @var
La propriété $service ait un setteur, ou soit déclarée publique
Etant donné que les annotations ne sont jamais lues à l’exécution, il est nécessaire de générer le cache des contrôleurs :
Ubiquity init-cache -t=controllers
Reste à vérifier que le service est bien injecté, en allant à l’adresse /ClientController
.
Injection de service
Service
Créons maintenant un deuxième service, nécessitant une initialisation spéciale.
1 class ServiceWithInit{
2 private $init;
3
4 public function init(){
5 $this->init=true;
6 }
7
8 public function do(){
9 if($this->init){
10 echo 'init well initialized!';
11 }else{
12 echo 'Service not initialized';
13 }
14 }
15 }
Injection dans le contrôleur
1namespace controllers;
2
3 /**
4 * Controller Client
5 **/
6 class ClientController extends ControllerBase{
7
8 /**
9 * @autowired
10 * @var \services\Service
11 */
12 private $service;
13
14 /**
15 * @injected
16 */
17 private $serviceToInit;
18
19 public function index(){
20 $this->serviceToInit->do();
21 }
22
23 /**
24 * @param \services\Service $service
25 */
26 public function setService($service) {
27 $this->service = $service;
28 }
29
30 /**
31 * @param mixed $serviceToInit
32 */
33 public function setServiceToInit($serviceToInit) {
34 $this->serviceToInit = $serviceToInit;
35 }
36
37 }
Di déclaration
Dans app/config/config.php
, créez une nouvelle clé pour la propriété serviceToInit à injecter dans la partie di.
"di"=>["ClientController.serviceToInit"=>function(){
$service=new \services\ServiceWithInit();
$service->init();
return $service;
}
]
générer le cache des contrôleurs :
Ubiquity init-cache -t=controllers
Vérifier que le service est bien injecté en allant à l’adresse /ClientController
.
Note
Si le même service doit être utilisé dans plusieurs contrôleurs, utilisez la notation avec joker :
"di"=>["*.serviceToInit"=>function(){
$service=new \services\ServiceWithInit();
$service->init();
return $service;
}
]
Injection avec un nom
Si le nom du service à injecter est différent de la clé du tableau di, il est possible d’utiliser l’attribut name de l’annotation @injected.
Dans app/config/config.php
, créez une nouvelle clé pour la propriété serviceToInit à injecter dans la partie di.
"di"=>["*.service"=>function(){
$service=new \services\ServiceWithInit();
$service->init();
return $service;
}
]
/**
* @injected("service")
*/
private $serviceToInit;
Injection de service à l’exécution
Il est possible d’injecter des services à l’exécution, sans qu’ils aient été précédemment déclarés dans une classe contrôleur.
1namespace services;
2
3 class RuntimeService{
4 public function __construct($ctrl){
5 echo 'Service instanciation in '.get_class($ctrl);
6 }
7 }
Dans app/config/config.php
, ajouter la clé @exec dans la partie di.
"di"=>["@exec"=>"rService"=>function($ctrl){
return new \services\RuntimeService($ctrl);
}
]
Avec cette déclaration, le membre $rService, instance de RuntimeService, est injecté dans tous les contrôleurs.
Il est donc conseillé d’utiliser les commentaires de javadoc pour déclarer $rService dans les contrôleurs qui l’utilisent (pour obtenir la complétion de code sur $rService dans votre IDE).
1namespace controllers;
2
3 /**
4 * Controller Client
5 * property services\RuntimeService $rService
6 **/
7 class MyController extends ControllerBase{
8
9 public function index(){
10 $this->rService->do();
11 }
12 }