2

ルート名を渡す URL を生成できることを知っています

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

しかし、逆方向に情報を取得できますか? 現在の URL/URI から、ルート名を取得する必要があります。

実際のケース: トップ メニュー (html) である layout.phtml があります。メニューの現在のリンクは、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';  
?>

私は高速ルートを使用していますが、どのソリューションにも興味があります。ソリューションはビュー ファイルにある必要はありません。

4

3 に答える 3

4

私の調査によると、 public メソッドgetMatchedRouteName()のRouteResultインスタンスにそのような情報があります。問題は、ビューからこのインスタンスに到達する方法です。

RouteResult を取得できることはわかっていますが、ミドルウェアの __invoke() メソッドにある Request オブジェクトから取得します。

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

@timdev が推奨するように、既存のヘルパーUrlHelperでインスピレーションを見つけ、カスタム ビュー ヘルパーでほぼ同じ実装を行います。

要するに、2 つのクラスを作成します。

  1. メソッドsetRouteResult ()を使用した CurrentUrlHelperおよび
  2. __invoke ($req, $res, $next)を使用したCurrentUrlMiddleware

CurrentUrlMiddleware に CurrentUrlHelper を挿入し、__invoke() メソッドで適切な RouteResult インスタンスを使用してCurrentUrlHelper::setRouteResult()を呼び出します。後で、RouteResult インスタンスを含む CurrentUrlHelper を使用できます。どちらのクラスにも 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 に登録するだけで済みます。

依存関係.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,
],

最後に、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';  
?>
于 2016-06-29T13:57:07.917 に答える
0

テンプレート レンダラーを別のクラスでラップし、そこに 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から借用しています。

于 2016-06-30T11:17:18.073 に答える