Zend Framework 2: навигация

В моем контроллере я создаю объект Navigation и передаю его в представление

$navigation = new \Zend\Navigation\Navigation(array(
    array(
            'label' => 'Album',
            'controller' => 'album',
            'action' => 'index',
            'route' => 'album',
        ),
    ));

Там пытается использовать это

navigation($this->navigation)->menu() ?>

И получите ошибку:

Неустранимая ошибка: Zend \ Navigation \ Exception \ DomainException: Zend \ Navigation \ Page \ Mvc :: getHref не может быть выполнен, поскольку экземпляр Zend \ Mvc \ Router \ RouteStackInterface не создается в Zend \ View \ Helper \ Navigation \ AbstractHelper.php в строке 471

Но навигация, которую я использую в макете, так написана здесь:http://adam.lundrigan.ca/2012/07/quick-and-dirty-zf2-zend-navigation/ работает. В чем моя ошибка?

Спасибо.

Ответы на вопрос(3)

Проблема в отсутствии Маршрутизатора (или, если быть более точным,Zend\Mvc\Router\RouteStackInterface). Стек маршрутов представляет собой набор маршрутов и может использовать имя маршрута, чтобы превратить его в URL. В основном он принимает имя маршрута и создает для вас URL:

$url = $routeStack->assemble('my/route');

Это происходит на страницах MVCZend\Navigation тоже. На странице естьroute параметр и когда есть доступный маршрутизатор, страница собирает его 'Ваш собственный URL (или вZend\Navigation условия,href). Если вы не предоставляете маршрутизатор, он не может собрать маршрут и, таким образом, выдает исключение.

Вы должны внедрить роутер на каждой странице навигации:

$navigation = new Navigation($config);
$router     = $serviceLocator->get('router');

function injectRouter($navigation, $router) {
  foreach ($navigation->getPages() as $page) {
    if ($page instanceof MvcPage) {
      $page->setRouter($router);
    }

    if ($page->hasPages()) {
      injectRouter($page, $router);
    }
  }
}

Как видите, это рекурсивная функция, внедряющая маршрутизатор в каждую страницу. Скучная! Поэтому есть фабрика, чтобы сделать это для вас. Естьчетыре простых шага чтобы это произошло.

ПЕРВЫЙ ШАГ

Сначала поместите конфигурацию навигации в конфигурацию вашего модуля. Так же, как у вас естьdefault Навигация, вы можете создать второй.secondary

'navigation' => array(
    'secondary' => array(
        'page-1' => array(
            'label' => 'First page',
            'route' => 'route-1'
        ),
        'page-2' => array(
            'label' => 'Second page',
            'route' => 'route-2'
        ),
    ),
),

У вас есть маршруты к вашей первой странице (route-1) и вторая страница (route-2).

ШАГ ВТОРОЙ

Фабрика преобразует это в структуру объекта навигации, для этого нужно сначала создать класс. Создать файлSecondaryNavigationFactory.php в вашем каталоге MyModule / Navigation / Service.

namespace MyModule\Navigation\Service;

use Zend\Navigation\Service\DefaultNavigationFactory;

class SecondaryNavigationFactory extends DefaultNavigationFactory
{
    protected function getName()
    {
        return 'secondary';
    }
}

Смотри, я поставил имяsecondary здесь, который совпадает с вашей навигационной клавишей.

ТРЕТИЙ ШАГ

Вы должны зарегистрировать эту фабрику у менеджера сервиса. Тогда фабрика сможет это сделать »с работы и превратить файл конфигурации вZend\Navigation объект. Вы можете сделать это в вашем module.config.php:

'service_manager' => array(
    'factories' => array(
        'secondary_navigation' => 'MyModule\Navigation\Service\SecondaryNavigationFactory'
    ),
)

Видишь, я сделал услугуsecondary_navigation здесь, где фабрика вернетZend\Navigation экземпляр тогда. Если вы делаете сейчас$sm->get('secondary_navigation') вы увидите, что этоZend\Navigation\Navigation объект.

ШАГ ЧЕТВЕРТЫЙ

Скажите помощнику представления, чтобы использовать эту навигацию, а не по умолчанию. Помощник вида навигации принимает "навигация» параметр, где вы можете указать, какую навигацию вы хотите. В этом случае у сервис-менеджера есть сервисsecondary_navigation и это то, что нам нужно.

navigation('secondary_navigation')->menu() ?>

Теперь у вас будет навигацияsecondary используется в этом представлении помощник.

Раскрытие: этот ответ такой же, как я дал на этот вопрос:https://stackoverflow.com/a/12973806/434223

 Jeremy Hicks30 нояб. 2012 г., 07:15
Это отличный пример. Это работает, пока я не хочу использовать частичное представление для рендеринга. Я'Я использую это для моей основной навигации, но это не должноне имеет значения. Вот'что яиспользуя: echo $ this->навигации (»навигация») ->Меню () ->setPartial (массив (»navigation.phtml ','Заявка')); Неустранимая ошибка: Zend \ ServiceManager \ Exception \ ServiceNotFoundException: Zend \ ServiceManager \ ServiceManager :: get не удалось получить или создать экземпляр для меню в / myapp / vendor / zendframework / zendframework / library / Zend / View / Helper / Navigation / AbstractHelper .php на линии 471

Кстати. ты ненужно определитьcontroller а такжеaction если вы определитеroute, только если ваш маршрут является общим и контроллер / действие являются переменными сегментами.

 Eremite08 окт. 2012 г., 21:32
Да, в Module.php в методе onBootstrap у меня точно такой же код. Что интересно, так это то, что помощник вида url работает правильно. Код$this->url('album/default', array('controller'=>'album', 'action'=>'edit', 'id' => $id)) работает очень хорошо и отображает ссылку на странице. Не понятно, что мешает правильному отображению меню. Если будут какие-то мысли, буду рад их услышать. Благодарю.
 Eremite08 окт. 2012 г., 21:06
Вы правы, спасибо за комментарии. Но если это так, исправьте ошибку на странице объявления. Единственный вариант, когда код работает, когда он выглядит так:$navigation = new \Zend\Navigation\Navigation(array( array( 'label' => 'Album', 'uri'=>'/' ), )); Когда URL-адрес устанавливается напрямую.
 Andreas Linden08 окт. 2012 г., 21:11
хм не знаю, но у вас есть это в вашем module.php?$application = $e->getApplication(); $eventManager = $application->getEventManager(); $moduleRouteListener = new ModuleRouteListener(); $moduleRouteListener->attach($eventManager);

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

Вот'Как я использую это в представлении:

$navigation = $this->navigation();
$navigation->addPage(
    array(
        'route' => 'language',
        'label' => 'language.list.nav'
    )
);
$this->registerNavigationRouter($navigation);
echo $navigation->menu()->render();

Помощник вида:

serviceLocator = $serviceLocator;
    }

    public function getServiceLocator()
    {
        return $this->serviceLocator;
    }

    public function __invoke(Navigation $navigation)
    {
        $router = $this->getRouter();
        foreach ($navigation->getPages() as $page) {
            if ($page instanceof Mvc) {
                $page->setRouter($router);
            }
        }
    }

    protected function getRouter()
    {
        $router = $this->getServiceLocator()->getServiceLocator()->get('router');
        return $router;
    }
}

Дон»не забудьте добавить помощник вида в вашей конфигурации как вызываемый экземпляр:

'view_helpers' => array(
    'invokables' => array(
        'registerNavigationRouter' => 'JarJar\View\Helper\RegisterNavigationRouter'
    )
),

Это'не очень хорошее решение, но оно работает.

Ваш ответ на вопрос