web-dev-qa-db-fra.com

Zend Framework 2: visualisez la route correspondante

J'apprends actuellement ZF2 en développant une petite application MVC basée approximativement sur l'application squelette. À l'heure actuelle, j'essaie de masquer certains éléments HTML fixes en fonction de la route recherchée: à titre d'exemple, je ne souhaite pas que le menu principal s'affiche pendant la phase de connexion. 

Je peux le faire facilement en transmettant les paramètres de bascule en tant que valeurs de retour des actions du contrôleur, mais cela ne me convient pas. Je voudrais simplement vérifier la route correspondante dans la présentation et composer celle-ci en conséquence. 

Le problème, c'est que je ne sais pas comment obtenir l'itinéraire correspondant dans le modèle. Est-ce possible? Existe-t-il d'autres solutions pour éviter l'ajout d'une logique de présentation dans les contrôleurs?

Edit après quelques bons travaux de Frankenstein, j'ai pu trouver une solution à cela. J'aime l'idée d'utiliser un assistant, alors j'ai juste essayé de lui passer l'objet Application, à partir de la fonction boostrap du module principal:

$app = $e->getApplication();
$serviceManager = $app->getServiceManager();
....
$serviceManager->get('viewhelpermanager')->setFactory('getRoute', function($sm) use ($app) {
    return new Helper\GetRoute($app);
});

et la fonction d'assistance:

use Zend\View\Helper\AbstractHelper;

class GetRoute extends AbstractHelper {
    private $sm;

    public function __construct($app) {
        $this->sm = $app->getServiceManager();
    }

    public function echoRoute() {
        $router = $this->sm->get('router');
        $request = $this->sm->get('request');

        $routeMatch = $router->match($request);
        if (!is_null($routeMatch))
            echo $routeMatch->getMatchedRouteName();
    }
}

peut-être y a-t-il un moyen plus propre, plus ZF2ish de le faire ...

11
risteli

Une autre solution sans nouvelle correspondance

$routeMatch = $serviceLocator->get('Application')->getMvcEvent()->getRouteMatch();

echo $routeMatch->getMatchedRouteName();
29
MarkusM

Il existe un moyen d'obtenir le gestionnaire de service dans la mise en page:

$sm = $this->getHelperPluginManager()->getServiceLocator();

et alors vous pouvez accéder à $sm->get('router') etc.

12
Denis Ryabov

Vous pouvez créer un assistant de vue qui implémente ServiceManagerAwareInterface. Ensuite, à l'intérieur de l'assistant View, utilisez l'instance ServiceManager pour extraire le routeur et les objets de requête, puis reconstruisez la correspondance de route.

$services = $this->getServiceManager();

$router = $services->get('router');
$request = $services->get('request');

$routeMatch = $router->match($request);
echo $routeMatch->getMatchedRouteName();

Je vous recommande également d'écrire l'assistant View afin que le code ne soit déclenché qu'une seule fois par demande.

9
DrBeza

Lorsque vous passez à ZF3, vous devriez envisager d'utiliser cette méthode ... puisque getLocator n'est plus disponible (et que ce n'est pas correct, l'injecter).

  1. Créer l'assistant

    namespace Application\View\Helper;
    
    use Zend\Http\Request;
    use Zend\Router\RouteStackInterface;
    use Zend\View\Helper\AbstractHelper;
    
    /**
     * Helper to get the RouteMatch
     */
    class RouteMatch extends AbstractHelper
    {
        /**
         * RouteStackInterface instance.
         *
         * @var RouteStackInterface
         */
        protected $router;
    
        /**
         * @var Request
         */
        protected $request;
    
        /**
         * RouteMatch constructor.
         * @param RouteStackInterface $router
         * @param Request $request
         */
        public function __construct(RouteStackInterface $router, Request $request)
        {
            $this->router = $router;
            $this->request = $request;
        }
    
        /**
         * @return \Zend\Router\RouteMatch
         */
        public function __invoke()
        {
            return $this->router->match($this->request);
        }
    }
    
  2. Créer une usine pour cette aide

    namespace Application\View\Helper;
    
    use Interop\Container\ContainerInterface;
    use Zend\ServiceManager\Factory\FactoryInterface;
    
    class RouteMatchFactory implements FactoryInterface
    {
        public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
        {
            $router = $container->get('router');
            $request = $container->get('request');
    
            return new RouteMatch($router, $request);
        }
    
    }
    
  3. Appelez votre fabrique sur votre Module.php et créez un alias pour cela.

    public function getViewHelperConfig()
    {
        return array(
            'factories' => array(
                RouteMatch::class => RouteMatchFactory::class,
            ),
            'aliases' => array(
                'routeMatch' => RouteMatch::class,
            )
        );
    }
    

C'est ça ... vous avez un RouteMatch Helper utilisant les nouvelles normes ZF3.

Au revoir!

5
Rodrigo Boratto

En vue, vous pouvez utiliser:

$this->getHelperPluginManager()->getServiceLocator()->get('request')->getUri()->getPath();

ou

$this->getHelperPluginManager()->getServiceLocator()->get('request')->getUri()->toString();
2
Decrypter

Je crois que vous pouvez le résoudre en trouvant les noms d'action/contrôleur:

$controller = $this->getRequest()->getControllerName();
$action = $this->getRequest()->getActionName();

Une fois que vous connaissez l'action, vous pouvez avoir des conditions spécifiques pour activer les sections de la mise en page.

1
Al-Punk

Je vois que tu peux utiliser

$this->getHelperPluginManager()->getServiceLocator()->get('Application')->getMvcEvent()->getRouteMatch()->getMatchedRouteName();
1
Tomasz

Informations supplémentaires sur le message "Rodrigo Boratto" pour l'intégration de getRouteMatch dans ZF3 (je ne peux pas commenter car je dispose de moins de 50 repo ...)

Dans la vue auxiliaire, classez ces lignes:

use Zend\Mvc\Router\RouteMatch as MvcRouteMatch;
use Zend\Mvc\Router\RouteStackInterface;

devrait être:

use Zend\Router\RouteMatch as MvcRouteMatch;
use Zend\Router\RouteStackInterface;

Je ne sais pas quand ils ont apporté cette modification, mais les fichiers se trouvent dans l'espace de noms Zend\Router.

P.S. J'utilise compositeur si ça compte.

1
Botman

Dans n'importe quelle vue ou disposition, vous pouvez tester l'itinéraire avec cette fonction:

<?php function itsRoute($routeName){
    $flag = false;
    if($this->serverUrl(true) == $this->url($route,[],['force_canonical'=>true]))){
        $flag = true;
    }

    return $flag;
}
0
albert

Mon contrôleur:

    <?PHP
    namespace SomeName\Controller;

    use Zend\Mvc\Controller\AbstractActionController;
    use Zend\View\Model\ViewModel;

    class SomeController extends AbstractActionController
    {
        public function getIdAction()
        {
            $id = $this->params()->fromRoute('id', 0);
            return new ViewModel(array(
                'id' => $id,
            ));
        }
    }

Mon routeur:

    <?php
    return array(
        'controllers' => array(
            'invokables' => array(
                'SomeName\Controller\Some' => 'SomeName\Controller\SomeController',
            ),
        ),

        'router' => array(
            'routes' => array(
                'testId' => array(
                    'type'    => 'segment',
                    'options' => array(
                        'route'    => '/[:id]',
                        'constraints' => array(
                            'id' => '\d*',
                        ),
                        'defaults' => array(
                            'controller' => 'SomeName\Controller\Some',
                            'action'     => 'getId',
                        ),
                    ),
                ),
            ),
        ),

        'view_manager' => array(
            'template_path_stack' => array(
                'album' => __DIR__ . '/../view',
            ),
        ),
    );
0
Josh