Une petite bafouille pour me rappeler comment on injecte les dépendances dans le constructeur du contrôleur
Fonctionne sur ZF2 2.1.5+
Nous souhaitons avoir des dépendances obligatoires dans notre contrôleur... Pourquoi pas après tout ? Admettons que le contrôleur ne peut pas fonctionner si les dépendances manquent. Mais comment surcharger le constructeur alors que le contrôleur est instancié par l'application MVC ? On pourrait, bien sûr, hacker le code de l'application, mais ce n'est pas ce que nous voulons vraiment, n'est-ce pas ?
Les dépendances sont obligatoires dans notre contrôleur
// module/MyModule/src/MyModule/Controller/IndexController.php
<?php
namespace MyModule\Controller ;
use MyModule\Entity\DependencyAInterface ;
use MyModule\Form\DependencyBInterface ;
use Zend\Mvc\Controller\AbstractActionController ;
class IndexController extends AbstractActionController
{
protected $dependencyA ;
protected $dependencyB ;
public function __construct(
DependencyAInterface $depA,
DependencyBInterface $debB
)
{
$this->dependencyA = $depA ;
$this->dependencyB = $depB ;
}
public function indexAction()
{
// just use $this->dependencyA and $this->dependencyB as normal
}
}
Maintenant, nous avons besoin d'un Factory, pour pouvoir accéder au constructeur du contrôleur.
Créer le controller factory
// module/MyModule/src/MyModule/Factory/IndexControllerFactory.php
<?php
namespace MyModule\Factory ;
use MyModule\Controller\WriteController ;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface ;
class IndexControllerFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
// cette ligne est obligatoire, même si elle paraît redondante
$realServiceLocator = $serviceLocator->getServiceLocator() ;
$entityDepA = $realServiceLocator->get('DependencyEntity') ;
$formDepB = $realServiceLocator->get('FormElementManager')->get('DependencyForm') ;
return new IndexController( // voici notre contrôleur
$entityDepA,
$formDepB
) ;
}
}
Et voilaaaa
Et nous avons injecté les dépendances dans le contrôleur sans coup férir.
C'est pas fini, maintenant, au tour du Service Manager
// module/MyModule/Module.php
<?php
// bref, on sait tous ce qu'il y a là
...
public function getServiceConfig()
{
return array(
'invokables' => array(
'DependencyForm' => 'MyModule\Form\MyForm',
),
'factories' => array(
'DependencyEntity' => function($sm) {
// n'importe quoi comprenant les injections de dépendances, bien sûr
return $entity ;
},
),
) ;
}
...
Maintenant, comment dire à l'application qu'elle ne devrait plus utiliser le contrôleur tel quel mais qu'elle devrait utiliser le contrôleur qui a été instancié à partir de notre factory ?
Allez hop, voyons la configuration du module. On se souvient de la clé 'controllers' qui se trouve là et qui nous sert à déclarer nos contrôleurs mmmh ??? oui oui oui, exactement, c'est de ça qu'il s'agit...
La clé 'controllers'
On avait quelquechose comme ça dans cette clé :
// module/MyModule/config/module.config.php
<?php
return array(
'controllers' => array(
'invokables' => array(
'ModuleController\Index' => 'MyModule\Controller\IndexController',
),
),
);
Maintenant, on veut utiliser la factory à la place
// module/MyModule/config/module.config.php
<?php
return array(
'controllers' => array(
'factories' => array(
'ModuleController\Index' => 'MyModule\Factory\IndexControllerFactory',
),
),
);
Surtout, il faut bien veiller à réutiliser le même alias (ModuleController\Index
). Comme ça, on n'aura pas à changer le routeur également...
Tadaaaa