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

app/services/Service.php
 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

app/services/Service.php
 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.

app/services/ServiceWithInit.php
 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

app/controllers/ClientController.php
 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.

app/services/RuntimeService.php
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).

app/controllers/MyController.php
 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     }