1

Я знаю, что я могу генерировать URL передавая имя маршрутаКак получить соответствует названию маршрута в View - Zend выразительный

<?php echo $this->url('route-name') #in view file ?> 

Но я могу получить информацию в обратном направлении? Из текущего URL/URI мне нужно получить имя маршрута.

Настоящий случай: у меня есть layout.phtml, где находится верхнее меню (html). Текущая ссылка в меню должна быть отмечена классом css. Итак, пример, в котором я нуждаюсь:

<?php // in layout.phtml file 
    $index_css = $this->getRouteName() == 'home-page' ? 'active' : 'none'; 
    $about_css = $this->getRouteName() == 'about'  ? 'active' : 'none'; 
    $contact_css = $this->getRouteName() == 'contact' ? 'active' : 'none'; 
?> 

Я использую быстрый маршрут, но я заинтересован в любом решении. Решение не обязательно должно находиться в файле View.

+0

Возможно, вам нужен помощник, чтобы получить маршрутизатор, который имеет метод 'match'. [Неиспользованная предполагаемая реализация] (http://stackoverflow.com/a/36337414/2908724). – bishop

ответ

3

Из моего исследования, есть такая информация в RouteResult экземпляр в общедоступном методе getMatchedRouteName(). Проблема заключается в том, как добраться до этого экземпляра из представления.

Мы знаем, что мы можем получить RouteResult, но из объекта Request, который находится в методе __invoke() промежуточного ПО.

public function __invoke($request, $response, $next){ 
    # instance of RouteResult 
    $routeResult = $request->getAttribute('Zend\Expressive\Router\RouteResult'); 
    $routeName = $routeResult->getMatchedRouteName(); 
    // ... 
} 

Как @timdev рекомендовал нам найти вдохновение в существующих помощник UrlHelper и делаем почти то же implementation в пользовательском View Helper.

Одним словом, мы создадим 2 класса.

  1. CurrentUrlHelper с помощью метода setRouteResult() и
  2. CurrentUrlMiddleware с __invoke ($ REQ, $ Рез, $ следующая)

Мы впрыскивать CurrentUrlHelper в CurrentUrlMiddleware и в методе __invoke() вызывают CurrentUrlHelper :: setRouteResult() с соответствующим экземпляром RouteResult. Позже мы можем использовать наш CurrentUrlHelper с экземпляром RouteResult. Оба класса должны иметь фабрику.

class CurrentUrlMiddlewareFactory { 
    public function __invoke(ContainerInterface $container) { 
     return new CurrentUrlMiddleware(
      $container->get(CurrentUrlHelper::class) 
     ); 
    } 
} 

class CurrentUrlMiddleware { 
    private $currentUrlHelper; 

    public function __construct(CurrentUrlHelper $currentUrlHelper) { 
     $this->currentUrlHelper = $currentUrlHelper; 
    } 

    public function __invoke($request, $response, $next = null) { 
     $result = $request->getAttribute('Zend\Expressive\Router\RouteResult'); 
     $this->currentUrlHelper->setRouteResult($result); 

     return $next($request, $response); # continue with execution 
    } 
} 

И наш новый помощник:

class CurrentUrlHelper { 
    private $routeResult; 

    public function __invoke($name) { 
     return $this->routeResult->getMatchedRouteName() === $name; 
    } 

    public function setRouteResult(RouteResult $result) { 
     $this->routeResult = $result; 
    } 
} 


class CurrentUrlHelperFactory{ 
    public function __invoke(ContainerInterface $container){ 
     # pull out CurrentUrlHelper from container! 
     return $container->get(CurrentUrlHelper::class); 
    } 
} 

Теперь нам нужно только зарегистрировать наш новый вид Helper и Middleware в конфиги:

dependencies.global.php

'dependencies' => [ 
    'invokables' => [ 
     # dont have any constructor! 
     CurrentUrlHelper::class => CurrentUrlHelper::class, 
    ], 
] 

middleware-pipeline.globa l.php

'factories' => [ 
    CurrentUrlMiddleware::class => CurrentUrlMiddlewareFactory::class, 
], 
'middleware' => [ 
    Zend\Expressive\Container\ApplicationFactory::ROUTING_MIDDLEWARE, 
    Zend\Expressive\Helper\UrlHelperMiddleware::class, 
    CurrentUrlMiddleware::class,   # Our new Middleware 
    Zend\Expressive\Container\ApplicationFactory::DISPATCH_MIDDLEWARE, 
], 

И, наконец, мы можем зарегистрировать наш View Helper в templates.global.PHP

'view_helpers' => [ 
    'factories' => [ 
     # use factory to grab an instance of CurrentUrlHelper 
     'currentRoute' => CurrentUrlHelperFactory::class 
    ] 
], 
  • важно зарегистрировать нашу межплатформенное после ROUTING_MIDDLEWARE и перед DISPATCH_MIDDLEWARE!

  • Кроме того, у нас есть CurrentUrlHelperFactory, чтобы присвоить его ключу 'currentRoute'.

Теперь вы можете использовать помощника в любом файле шаблона :)

<?php // in layout.phtml file 
    $index_css = $this->currentRoute('home-page') ? 'active' : 'none'; 
    $about_css = $this->currentRoute('about') ? 'active' : 'none'; 
    $contact_css = $this->currentRoute('contact') ? 'active' : 'none'; 
?> 
+0

Уверен, что вы можете использовать Reflection, но этот метод защищен по какой-либо причине. Этот трюк может не работать больше в будущем. – xtreamwayz

+1

Да, отражение было быстрым, но не очень хорошим решением. Я меняю его. – tasmaniski

+0

$ routeResult = $ request-> getAttribute ('Zend \ Expressive \ Router \ RouteResult'); $ routeName = $ routeResult-> getMatchedRouteName(); Я думаю, что было бы лучше заменить это на: $ router = $ container-> get (RouterInterface :: class); $ router-> match ($ request) -> getMatchedRouteName(); – Andriy

0

Как вы отмечаете в вашей уверенности в ответе, UrlHelper полезная вещь, чтобы заметить. Однако создание нового помощника, зависящего от UrlHelper (и отражения), не является идеальным.

Вам лучше написать свой собственный помощник, вдохновленный UrlHelper, но не зависящий от него.

Вы можете посмотреть код для UrlHelper, UrlHelperFactory и UrlHelperMiddleware, чтобы сообщить о своей собственной реализации.

+0

Спасибо! Я действительно нашел хорошее вдохновение в существующем UrlHelper :) – tasmaniski

0

Вы можете обернуть средство визуализации шаблона в другом классе и передать запрос туда, вычесть то, что вам нужно, и вставить его в реальный рендеринг.

Действие промежуточного слоя:

class Dashboard implements MiddlewareInterface 
{ 
    private $responseRenderer; 

    public function __construct(ResponseRenderer $responseRenderer) 
    { 
     $this->responseRenderer = $responseRenderer; 
    } 

    public function __invoke(Request $request, Response $response, callable $out = null) : Response 
    { 
     return $this->responseRenderer->render($request, $response, 'common::dashboard'); 
    } 
} 

Новый класс обертку:

<?php 

declare(strict_types = 1); 

namespace Infrastructure\View; 

use Psr\Http\Message\ResponseInterface as Response; 
use Psr\Http\Message\ServerRequestInterface as Request; 
use Zend\Diactoros\Stream; 
use Zend\Expressive\Router\RouteResult; 
use Zend\Expressive\Template\TemplateRendererInterface; 

class ResponseRenderer 
{ 
    private $templateRenderer; 

    public function __construct(TemplateRendererInterface $templateRenderer) 
    { 
     $this->templateRenderer = $templateRenderer; 
    } 

    public function render(Request $request, Response $response, string $templateName, array $data = []) : Response 
    { 
     $routeResult  = $request->getAttribute(RouteResult::class); 
     $data['routeName'] = $routeResult->getMatchedRouteName(); 

     $body = new Stream('php://temp', 'wb+'); 
     $body->write($this->templateRenderer->render($templateName, $data)); 
     $body->rewind(); 

     return $response->withBody($body); 
    } 
} 

Код заимствовано из GitHub.

Смежные вопросы