私は現在、おおよそスケルトンアプリに基づいた小さなMVCアプリケーションを開発することでZF2を学んでいます。現在、一致したルートに基づいていくつかの固定HTML要素を非表示にしようとしています。例として、ログインフェーズ中にメインメニューを表示したくありません。
コントローラーアクションからの戻り値としてトグルパラメーターを渡すことで簡単にそれを行うことができますが、それは正しくないので、レイアウトから一致するルートを確認し、それに応じてレイアウトを構成したいと思います。
問題は、テンプレートで一致するルートを取得する方法がわからないことです。これは可能ですか?コントローラーにレイアウトロジックを追加しないようにする他のソリューションはありますか?
編集フランケンシュタインのよい仕事をした後、私はこれに対する解決策を見つけることができました。ヘルパーを使用するアイデアが好きなので、メインモジュールのboostrap関数からApplicationオブジェクトを渡そうとしました:
$app = $e->getApplication();
$serviceManager = $app->getServiceManager();
....
$serviceManager->get('viewhelpermanager')->setFactory('getRoute', function($sm) use ($app) {
return new Helper\GetRoute($app);
});
そしてヘルパー関数:
use Zend\View\Helper\AbstractHelper;
class GetRoute extends AbstractHelper {
private $sm;
public function __construct($app) {
$this->sm = $app->getServiceManager();
}
public function echoRoute() {
$router = $this->sm->get('router');
$request = $this->sm->get('request');
$routeMatch = $router->match($request);
if (!is_null($routeMatch))
echo $routeMatch->getMatchedRouteName();
}
}
おそらく、これを行うためのよりクリーンでよりZF2的な方法があるでしょう...
新しい対戦のない別の解決策
$routeMatch = $serviceLocator->get('Application')->getMvcEvent()->getRouteMatch();
echo $routeMatch->getMatchedRouteName();
レイアウトでサービスマネージャーを取得する方法があります。
_$sm = $this->getHelperPluginManager()->getServiceLocator();
_
その後、$sm->get('router')
などにアクセスできます。
ServiceManagerAwareInterfaceを実装するビューヘルパーを作成できます。次に、ビューヘルパー内でServiceManagerインスタンスを使用してルーターとリクエストオブジェクトの両方を取得し、ルートの一致を再構築します。
$services = $this->getServiceManager();
$router = $services->get('router');
$request = $services->get('request');
$routeMatch = $router->match($request);
echo $routeMatch->getMatchedRouteName();
コードがリクエストごとに1回だけトリガーされるように、Viewヘルパーを作成することもお勧めします。
ZF3に移行するときは、このメソッドの使用を検討する必要があります... getLocatorはもう利用できません(そして、正しいインジェクトではありません)。
ヘルパーを作成する
namespace Application\View\Helper;
use Zend\Http\Request;
use Zend\Router\RouteStackInterface;
use Zend\View\Helper\AbstractHelper;
/**
* Helper to get the RouteMatch
*/
class RouteMatch extends AbstractHelper
{
/**
* RouteStackInterface instance.
*
* @var RouteStackInterface
*/
protected $router;
/**
* @var Request
*/
protected $request;
/**
* RouteMatch constructor.
* @param RouteStackInterface $router
* @param Request $request
*/
public function __construct(RouteStackInterface $router, Request $request)
{
$this->router = $router;
$this->request = $request;
}
/**
* @return \Zend\Router\RouteMatch
*/
public function __invoke()
{
return $this->router->match($this->request);
}
}
このヘルパーのファクトリを作成します
namespace Application\View\Helper;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class RouteMatchFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$router = $container->get('router');
$request = $container->get('request');
return new RouteMatch($router, $request);
}
}
Module.php
とエイリアスを作成します。
public function getViewHelperConfig()
{
return array(
'factories' => array(
RouteMatch::class => RouteMatchFactory::class,
),
'aliases' => array(
'routeMatch' => RouteMatch::class,
)
);
}
それだけです...新しいZF3標準を使用するRouteMatchヘルパーがあります。
バイバイ!
ビューで使用できます:
$this->getHelperPluginManager()->getServiceLocator()->get('request')->getUri()->getPath();
または
$this->getHelperPluginManager()->getServiceLocator()->get('request')->getUri()->toString();
アクション/コントローラー名を見つけることで解決できると思います。
$controller = $this->getRequest()->getControllerName();
$action = $this->getRequest()->getActionName();
アクションがわかったら、レイアウトのセクションを有効にするための特定の条件を設定できます。
使えると思います
$this->getHelperPluginManager()->getServiceLocator()->get('Application')->getMvcEvent()->getRouteMatch()->getMatchedRouteName();
ZF3にgetRouteMatchを統合するための「Rodrigo Boratto」投稿に関する追加情報(50未満のリポジトリがあるためコメントできません...)
ビューヘルパーファイルでこれらの行:
use Zend\Mvc\Router\RouteMatch as MvcRouteMatch;
use Zend\Mvc\Router\RouteStackInterface;
でなければなりません:
use Zend\Router\RouteMatch as MvcRouteMatch;
use Zend\Router\RouteStackInterface;
彼らがいつ変更したかはわかりませんが、ファイルはZend\Router名前空間にあります。
追伸必要に応じて、composerを使用します。
どのビューまたはレイアウトでも、この機能を使用してルートをテストできます。
<?php function itsRoute($routeName){
$flag = false;
if($this->serverUrl(true) == $this->url($route,[],['force_canonical'=>true]))){
$flag = true;
}
return $flag;
}
私のコントローラー:
<?PHP
namespace SomeName\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class SomeController extends AbstractActionController
{
public function getIdAction()
{
$id = $this->params()->fromRoute('id', 0);
return new ViewModel(array(
'id' => $id,
));
}
}
私のルーター:
<?php
return array(
'controllers' => array(
'invokables' => array(
'SomeName\Controller\Some' => 'SomeName\Controller\SomeController',
),
),
'router' => array(
'routes' => array(
'testId' => array(
'type' => 'segment',
'options' => array(
'route' => '/[:id]',
'constraints' => array(
'id' => '\d*',
),
'defaults' => array(
'controller' => 'SomeName\Controller\Some',
'action' => 'getId',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'album' => __DIR__ . '/../view',
),
),
);