A free and open-source book on ZF3 for beginners

Translation into this language is not yet finished. You can help this project by translating the chapters and contributing your changes.

4.9. Déclaration des controleurs

Toutes les classes contrôleurs appartenant à un module doivent être déclarées dans le fichier de configuration spécifique, le fichier module.config.php. Si votre contrôleur ne dépend pas de services spécifique (il n'a pas de dépendances), vous pouvez le déclarer comme celà :

<?php
use Zend\ServiceManager\Factory\InvokableFactory;

return [
    // ...
    
    'controllers' => [
        'factories' => [
            Controller\IndexController::class => InvokableFactory::class
            // Déclarez les autres contrôleurs ici
        ],
    ],
    
    // ...
];

Ligne 7, nous pouvons voir la clé controllers, elle contient en sous-clé des factories. Pour déclarer un contrôleur, ajoutez une ligne au format clé => valeur. La clé doit être le nom complet de la classe du contrôleur, comme \Application\Controller\IndexController (nous pouvons utiliser le mot-clé PHP ::class pour la résolution de son nom). La valeur doit correspondre au nom de la classe factory qui génère le contrôleur. Dans notre cas, nous utilisons la norme InvokableFactory, mais vous pouvez créer une classe factory spécifique si vous en avez besoin.

En utilisant la classe InvokableFactory, vous indiquez à Zend Framework qu'il peut instancier le contrôleur avec un nouvel opérateur. C'est la manière la plus simple d'instancier un contrôleur. Vous pouvez également déclarer votre propre classe factory pour créer une instance du contrôleur et y injecter des dépendances.

4.9.1. Déclaration d'un Controller Factory

Si votre classe de contrôleur doit appeler un service (cela arrive très souvent), vous devez demander ce service au service manager (voir le chapitre Operation du site) et le passer au constructeur du contrôleur, ensuite le contrôleur déclare le service que vous avez passé dans une propriété privée pour un usage interne (également appelé injection de dépendance).

Cette procédure est généralement implémentée dans une classe factory. Par exemple, supposons que notre classe de contrôleur doit utiliser un service CurrencyConverter qui convertira de l'argent en USD en EUR. La classe factory de notre contrôleur ressemblera à ci-dessous:

<?php 
namespace Application\Controller\Factory;

use Zend\ServiceManager\Factory\FactoryInterface;
use Application\Service\CurrencyConverter;
use Application\Controller\IndexController;

// Factory class
class IndexControllerFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, 
                     $requestedName, array $options = null) 
    {
        // Obtention de l'instance du service CurrencyConverter auprès du service manager.
        $currencyConverter = $container->get(CurrencyConverter::class);
        
        // Création d'une instance du contrôleur et transmission de la dépendance au constructeur du contrôleur.
        return new IndexController($currencyConverter);	
    }
}

Ensuite, vous déclarez le contrôleur de la même manière, mais spécifiez la classe factory que nous venons d'écrire:

<?php
return [
    // ...
    
    'controllers' => [
        'factories' => [
            Controller\IndexController::class => Controller\Factory\IndexControllerFactory::class
        ],
    ],
    
    // ...
];

Si vous connaissez Zend Framework 2, vous remarquerez peut-être que les choses sont maintenant un peu différentes. Dans ZF2, il y avait la méthode getServiceLocator() dans la classe de base AbstractActionController qui permettait d'obtenir les dépendances du contrôleur sans l'utilisation de classe factory. Dans ZF3, vous devez transmettre les dépendances explicitement. C'est un peu plus galère, mais cela évite les dépendances "cachées" et rend votre code plus clair et plus facile à comprendre.

4.9.2. LazyControllerAbstractFactory

L'écriture d'une classe factory pour presque tous les contrôleurs peut sembler ennuyeux à première vue. Si vous êtes paresseux et que vous ne voulez pas le faire, vous pouvez utiliser la classe factory LazyControllerAbstractFactory.

Cette classe factory LazyControllerAbstractFactory utilise reflexion pour déterminer les services dont votre contrôleur a besoin. Vous n'avez qu'à saisir les arguments du constructeur du contrôleur, et la classe factory récupérera elle-même les services demandé pour les transmettre au constructeur.

Par exemple, pour injecter le service CurrencyConverter dans votre contrôleur, assurez-vous que son constructeur ressemble à :

namespace Application\Controller;

use Application\Service\CurrencyConverter;

class IndexController extends AbstractActionController
{
    // Ici, nous allons déclarer le service pour un usage interne.
    private $currencyConverter;
    
    // Saisissez les arguments du constructeur pour obtenir les dépendances.
    public function __construct(CurrencyConverter $currencyConverter)
    {
        $this->currencyConverter = $currencyConverter;
    }
}

Ensuite, vous déclarez le contrôleur de la même manière, mais spécifiez la classe factory LazyControllerAbstractFactory :

<?php
use Zend\Mvc\Controller\LazyControllerAbstractFactory;

return [
    // ...
    
    'controllers' => [
        'factories' => [
            Controller\IndexController::class => LazyControllerAbstractFactory::class
        ],
    ],
    
    // ...
];

Top