Inyección de dependencia

Nota

Por razones de rendimiento, la inyección de dependencias no se utiliza en la parte central del framework.

La inyección de dependencia (DI) es un patrón de diseño utilizado para implementar IoC.
Permite la creación de objetos dependientes fuera de una clase y proporciona esos objetos a una clase a través de diferentes formas. Usando DI, movemos la creación y vinculación de los objetos dependientes fuera de la clase que depende de ella.

Nota

Ubiquity sólo soporta inyección de propiedades, para no requerir introspección en la ejecución.
Sólo los controladores soportan inyección de dependencias.

Servicio de autowiring

Creación de servicios

Crear un servicio

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 en el controlador

Crear un controlador que requiere el servicio

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     }

En el ejemplo anterior, Ubiquity busca e inyecta $service cuando se crea ClientController.

La anotación @autowired requiere que:
  • el tipo que se va a instanciar se declara con la anotación @var.

  • La propiedad $service tiene un setter, o si se declara pública

Como las anotaciones nunca se leen en tiempo de ejecución, es necesario generar la caché de los controladores:

Ubiquity init-cache -t=controllers

Queda por comprobar que el servicio se inyecta yendo a la dirección /ClientController.

Inyección de servicio

Servicio

Creemos ahora un segundo servicio, que requiere una inicialización especial.

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     }

Inyección en el controlador

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     }

Declaración Di

En app/config/config.php, crea una nueva clave para la propiedad serviceToInit para inyectar en la parte di.

"di"=>["ClientController.serviceToInit"=>function(){
                        $service=new \services\ServiceWithInit();
                        $service->init();
                        return $service;
                }
        ]

generar la caché de los controladores:

Ubiquity init-cache -t=controllers

Comprueba que el servicio está inyectado yendo a la dirección /ClientController.

Nota

Si se va a utilizar el mismo servicio en varios controladores, utilice la notación comodín :

"di"=>["*.serviceToInit"=>function(){
                        $service=new \services\ServiceWithInit();
                        $service->init();
                        return $service;
                }
        ]

Inyección con un nombre calificador

Si el nombre del servicio que se va a inyectar es diferente de la clave de la matriz di, es posible utilizar el atributo name de la anotación @injected.

En app/config/config.php, crea una nueva clave para la propiedad serviceToInit para inyectar en la parte di.

"di"=>["*.service"=>function(){
                        $service=new \services\ServiceWithInit();
                        $service->init();
                        return $service;
                }
        ]
/**
 * @injected("service")
 */
private $serviceToInit;

Inyección de servicios en tiempo de ejecución

Es posible inyectar servicios en tiempo de ejecución, sin que éstos hayan sido declarados previamente en las clases del controlador.

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     }

En app/config/config.php, crea la clave @exec en la parte di.

"di"=>["@exec"=>"rService"=>function($ctrl){
                        return new \services\RuntimeService($ctrl);
                }
        ]

Con esta declaración, el miembro $rService, instancia de RuntimeService, se inyecta en todos los controladores.
Es aconsejable utilizar los comentarios javadoc para declarar $rService en los controladores que lo utilizan (para obtener la finalización de código en $rService en su 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     }