[英]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個類。
我們將在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.