簡體   English   中英

如何在View中獲取匹配的路線名稱-Zend Expressive

[英]How to get matched route name in View - Zend Expressive

我知道我可以通過路由名稱生成URL

<?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文件中。

根據我的研究,在公用方法getMatchedRouteName()中的RouteResult實例中有此類信息。 問題是如何從視圖到達此實例。

我們知道我們可以從中間件的__invoke()方法中的Request對象獲得RouteResult。

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

按照@timdev的建議,我們將在現有的助手UrlHelper中找到靈感,並在自定義View Helper中進行幾乎相同的實現

簡而言之,我們將創建2個類。

  1. 使用方法setRouteResult()的 CurrentUrlHelper
  2. 帶有__invoke的 CurrentUrlMiddleware ($ req,$ res,$ next)

我們將在CurrentUrlMiddleware中注入CurrentUrlHelper,並在__invoke()方法中使用適當的RouteResult實例調用CurrentUrlHelper :: setRouteResult() 稍后,我們可以在其中使用帶有RouteResult實例的CurrentUrlHelper。 這兩個類都應該有一個工廠。

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

現在,我們只需要在配置中注冊新的View Helper和中間件:

dependencies.global.php

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

中間件pipeline.global.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 Helper。

'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';  
?>

正如您在自我回答中指出的那樣,UrlHelper是一個有用的注意事項。 但是,創建依賴於UrlHelper(和反射)的新幫助器並不理想。

最好編寫自己的幫助程序,啟發UrlHelper,但不要依賴它。

您可以查看UrlHelper,UrlHelperFactory和UrlHelperMiddleware的代碼來告知自己的實現。

您可以將模板渲染器包裝在另一個類中,然后將Request傳遞到那里,減去您需要的內容,然后將其注入到實際的模板渲染器中。

動作中間件:

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借來的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM