Zend Framework 2: get matched route in view

2019-02-08 17:24发布

I'm currently learning ZF2 by developing a small MVC application roughly based on the skeleton app. Right now I'm trying to hide some fixed HTML elements based on the route matched: just as an example, I don't want the main menu to show during the login phase.

I can do that easily by passing toggle parameters as return values from the controller actions, but it doesn't feel right, so I'd like to just check the matched route from the layout and compose the layout accordingly.

Problem is, I don't know how to get the matched route in the template. Is this possible? Are there other solutions to avoid adding layout logic into controllers?

Edit after some good Frankenstein work, I was able to find a solution for this. I like the idea of using a helper, so I just tried to pass it the Application object, from the boostrap function in the main module:

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

and the helper function:

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();
    }
}

perhaps there's a cleaner, more ZF2ish way to do this...

10条回答
Fickle 薄情
2楼-- · 2019-02-08 17:40

There is a way to get service manager in layout:

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

and then you can access $sm->get('router') etc.

查看更多
姐就是有狂的资本
3楼-- · 2019-02-08 17:42

When moving to ZF3, you should consider use this method... since getLocator isn't available anymore (and it's not correct inject it).

  1. Create the Helper

    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. Create a Factory for this helper

    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. Call your Factory on your Module.php and create an Alias for it.

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

That's it... you have a RouteMatch Helper using the new ZF3 standards.

Bye!

查看更多
劫难
4楼-- · 2019-02-08 17:45

At any view or layout, you are able to test route with this function:

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

    return $flag;
}
查看更多
该账号已被封号
5楼-- · 2019-02-08 17:47

My controller:

    <?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,
            ));
        }
    }

My Router:

    <?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',
            ),
        ),
    );
查看更多
再贱就再见
6楼-- · 2019-02-08 17:49

Another solution without a new match

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

echo $routeMatch->getMatchedRouteName();
查看更多
倾城 Initia
7楼-- · 2019-02-08 17:55

In view you can use:

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

or

$this->getHelperPluginManager()->getServiceLocator()->get('request')->getUri()->toString();
查看更多
登录 后发表回答