1

을 내가 경로 이름어떻게보기에 경로 이름을 일치하세요 - 젠드 표현

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

을 통과 URL을 생성 할 수 있습니다하지만 난 반대 방향으로 정보를 얻을 수 있다는 것을 알고? 현재 URL/URI에서 경로 이름을 가져와야합니다.

실제 사례 : layout.phtml은 어디에 최상위 메뉴 (html)입니까? 메뉴의 현재 링크를 CSS 클래스로 표시해야합니다. 그래서, 내가 필요한 것은 다음과 같습니다.

저는 빠른 경로를 사용하고 있지만 어떤 해결책이든 재미 있습니다. 솔루션은 뷰 파일에있을 필요는 없습니다.

+0

라우터를 얻으려면 도우미가 필요합니다. 라우터에는 'match' 메소드가 있습니다. [테스트되지 않은 구현] (http://stackoverflow.com/a/36337414/2908724). – bishop

답변

3

내 연구에서 public 메서드 getMatchedRouteName()에있는 RouteResult 인스턴스에 이러한 정보가 있습니다. 문제는보기에서이 인스턴스에 도달하는 방법입니다.

우리는 RouteResult를 얻을 수 있지만 미들웨어의 __invoke() 메소드에있는 요청 객체로부터 얻을 수 있음을 알고 있습니다.

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

는 @timdev 우리가 도우미 UrlHelper 기존에 영감을 발견하고 사용자 정의보기 도우미 거의 같은 implementation를 만들 것입니다 권장.

간단히 말해 2 개의 클래스를 생성합니다. 우리는 CurrentUrlMiddleware에 CurrentUrlHelper를 주입 할 방법 setRouteResult __invoke와()

  • CurrentUrlMiddleware ($의 REQ, $ 입술, $ 다음)
    1. CurrentUrlHelper __invoke() 메서드의 은 을 호출합니다. CurrentUrlHelper :: setRouteResult()에 적절한 RouteResult 인스턴스가 있습니다. 나중에 CurrentUrlHelper와 함께 RouteResult 인스턴스를 사용할 수 있습니다. 두 클래스 모두 Factory를 가져야합니다.

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

      지금 우리는 단지 CONFIGS에 우리의 새로운보기 도우미와 미들웨어를 등록해야합니다

      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, 
      ], 
      

      그리고 마침내 우리는 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에서 차용된다.