ZF2: Как получить Zend \ Navigation внутри настраиваемого маршрута?

У меня есть настраиваемый маршрутизатор, и я должен получить доступ к Zend\Navigation внутри этого настраиваемого маршрутизатора. Я искал поисковые запросы, искал и искал результаты: /

Все, что мне нужно, – найти узлы с параметром 'link', используя Zend \ Navigation в моей функции Alias ​​:: match.

Вот мой module.config.php:

 'navigation' => array( 'default' => array( 'account' => array( 'label' => 'Account', 'route' => 'node', 'pages' => array( 'home' => array( 'label' => 'Dashboard', 'route' => 'node', 'params' => array( 'id' => '1', 'link' => '/about/gallery' ), ), ), ), ), ), [...] 

И вот мой класс Alias:

 // file within ModuleName/src/ModuleName/Router/Alias.php namespace Application\Router; use Traversable; use Zend\Mvc\Router\Exception; use Zend\Stdlib\ArrayUtils; use Zend\Stdlib\RequestInterface as Request; use Zend\Mvc\Router\Http; use Zend\ServiceManager\ServiceLocatorAwareInterface; use Zend\ServiceManager\ServiceLocatorInterface; class Alias extends Http\Segment implements ServiceLocatorAwareInterface { public function setServiceLocator(ServiceLocatorInterface $serviceLocator) { $this->serviceLocator = $serviceLocator; return $this; } public function getServiceLocator() { return $this->serviceLocator; } public function match(Request $request, $pathOffset = null) { [...] return parent::match($request, $pathOffset); } } 

Редакция:

Теперь я знаю, что я должен добавить менеджера сервисов в свой настраиваемый маршрутизатор. Дайте мне знать, если вы знаете, как это сделать 🙂

Редакция:

Хорошо, это не настраиваемый маршрутизатор, а маршрут. Виноват. Я говорил на #zftalk irc chanell, и класс AliasSegment должен реализовывать ServiceLocatorAwareInterface . Хорошо, я пробовал, но теперь есть еще одна проблема.

В функции setServiceLocator я не могу получить service locator . Он возвращает нулевой объект, однако $serviceLocator – это класс Zend\Mvc\Router\RoutePluginManager .

 public function setServiceLocator(ServiceLocatorInterface $serviceLocator){ $sl = $serviceLocator->getServiceLocator(); var_dump($sl); // NULL } 

Любые идеи о том, как получить от Zend навигацию?

РЕДАКТИРОВАНИЕ

В соответствии с тем, что сказал @mmmshuddup, я изменил свой собственный класс маршрутизатора. (Новая версия выше). Также в моем Module.php , внутри функции onBootstrap , я добавил эту строку:

 $sm->setFactory('Navigation', 'Zend\Navigation\Service\DefaultNavigationFactory', true); 

Навигация работает и его экземпляр перед route поэтому он должен быть видимым в моем классе Alias, но это не так.

Я включил функцию match в классе Alias :

 $servicesArray = $this->getServiceLocator()->getRegisteredServices(); 

и $servicesArray почти пуст. Нет сервиса, нет фабрик. onBootstrap же строка, вставленная в onBootstrap , сразу после установки новой фабрики (как указано выше) возвращает массив с navigation и другими службами.

Вопрос в следующем: как я могу поделиться этим массивом (или ServiceManager) с моим настраиваемым маршрутизатором: Alias ?

Я должен сказать, что все, что я хочу сделать, было возможно в ZF1, и это было довольно легко.

РЕДАКТИРОВАТЬ

Я нашел решение. Ответ ниже

Solutions Collecting From Web of "ZF2: Как получить Zend \ Navigation внутри настраиваемого маршрута?"

Это связано с тем, что сам объект действительно не имеет объявленных свойств . Но если вы это сделаете:

 echo get_class($sl); 

Вы увидите, что это действительно экземпляр Zend\ServiceManager\ServiceManager

Вы должны иметь возможность получить свой экземпляр навигации, выполнив что-то вроде:

 $nav = $sl->get('Navigation'); 

РЕДАКТИРОВАТЬ:

Я просто заметил, что у вас есть кое-что в неправильном месте вашего кода. Вы вызываете getServiceLocator() на $serviceLocator который уже является экземпляром этого. Также вы вызываете его в setServiceLocator() . Вы должны изменить его на:

 // EDIT - file within ModuleName/src/Router/Alias.php namespace Application\Router; use Traversable; use Zend\Mvc\Router\Exception; use Zend\Stdlib\ArrayUtils; use Zend\Stdlib\RequestInterface as Request; use Zend\Mvc\Router\Http; class Alias extends Http\Segment implements ServiceLocatorAwareInterface { public function setServiceLocator(ServiceLocatorInterface $serviceLocator) { $this->serviceLocator = $serviceLocator; return $this; } public function getServiceLocator() { return $this->serviceLocator; } public function match(Request $request, $pathOffset = null) { $nav = $this->getServiceLocator()->get('Navigation'); // ... return parent::match($request, $pathOffset); } } 

Я нашел решение, но это НЕ элегантное решение, я думаю. Однако все работает отлично. Если кто-то знает недостатки этого решения, прокомментируйте этот ответ или добавьте еще один, лучше. Мне пришлось изменить идею @mmmshuddup ( вы можете прочитать разговор ).

Прежде всего, внедрение ServiceLocatorAwareInterface в пользовательский класс маршрута больше не требуется.

В Module.php внутри функции onBootstrap :

  $app = $e->getApplication(); $sm = $app->getServiceManager(); $sm->get('translator'); $eventManager = $e->getApplication()->getEventManager(); $moduleRouteListener = new ModuleRouteListener(); $moduleRouteListener->attach($eventManager); $sm->setFactory('Navigation', 'Zend\Navigation\Service\DefaultNavigationFactory', true); $nav = $sm->get('Navigation'); $alias = $sm->get('Application\Router\Alias'); $alias->setNavigation($nav); 

Сначала мы создаем Navigation фабрику в ServiceManager а затем в нашем обычном маршруте. После этого мы можем передать класс навигации в настраиваемый маршрут с setNavigation функции setNavigation . Чтобы завершить экземпляр нашего пользовательского маршрута, нам нужно получить getServiceConfig в том же файле:

  return array( 'factories' => array( 'Application\Router\Alias' => function($sm) { $alias = new \Application\Router\Alias('/node[/:id]'); return $alias; }, 'db_adapter' => function($sm) { $config = $sm->get('Configuration'); $dbAdapter = new \Zend\Db\Adapter\Adapter($config['db']); return $dbAdapter; }, ) ); 

И вот сложная часть. Этот экземпляр является временным. Во время маршрутизации этот класс будет создан еще один раз, и поэтому, я думаю, он не очень изящный. Мы должны вставить параметр в конструктор, но в этот момент значение этого параметра не имеет значения.

Пользовательский класс маршрута:

 // file within ModuleName/src/ModuleName/Router/Alias.php namespace Application\Router; use Traversable; use Zend\Mvc\Router\Exception; use Zend\Stdlib\ArrayUtils; use Zend\Stdlib\RequestInterface as Request; use Zend\Mvc\Router\Http; class Alias extends Http\Segment { private static $_navigation = null; public function match(Request $request, $pathOffset = null) { //some logic here //get Navigation $nav = self::$_navigation; return parent::match($request, $pathOffset); } public function setNavigation($navigation){ self::$_navigation = $navigation; } } 

Поскольку первый экземпляр является временным, мы должны собирать наш класс Navigation в статической переменной. Это ужасно, но хорошо работает. Возможно, есть способ создать экземпляр только один раз и в конфигурации маршрута получить экземпляр, но на данный момент это лучший ответ на мой вопрос. Просто достаточно и работает правильно.