5

在我的控制器中,我创建 Navigation 对象并将其传递给视图

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

那里试图使用它

<?php echo $this->navigation($this->navigation)->menu() ?>

并得到错误:

致命错误:Zend\Navigation\Exception\DomainException: Zend\Navigation\Page\Mvc::getHref 无法执行,因为 Zend\Mvc\Router\RouteStackInterface 实例在第 471 行的 Zend\View\Helper\Navigation\AbstractHelper.php 中组成

但是我在布局中使用的导航,如下所示:http: //adam.lundrigan.ca/2012/07/quick-and-dirty-zf2-zend-navigation/有效。我的错误是什么?

谢谢你。

4

3 回答 3

10

问题是缺少路由器(或更准确地说,是 a Zend\Mvc\Router\RouteStackInterface)。路由堆栈是路由的集合,可以使用路由名称将其转换为 url。基本上它接受一个路由名称并为您创建一个 url:

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

这也发生在 MVC 页面内部Zend\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,这就是我们需要的服务。

<?= $this->navigation('secondary_navigation')->menu() ?>

现在您将拥有secondary此视图助手中使用的导航。

披露:这个答案与我在这个问题上给出的答案相同:https ://stackoverflow.com/a/12973806/434223

于 2012-10-19T12:01:24.070 回答
2

顺便提一句。你不需要定义controlleraction如果你定义了 a route,只有当你的路由是通用的并且控制器/动作是可变段时。

于 2012-10-08T18:40:35.560 回答
0

问题确实是没有路由器就无法解决路由。我希望导航类能够解决这个问题,但显然你必须自己做。我刚刚写了一个视图助手来介绍带有 MVC 页面的路由器。

这是我在视图中使用它的方式:

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

视图助手:

<?php
namespace JarJar\View\Helper;

use Zend\View\Helper\AbstractHelper;
use Zend\View\Helper\Navigation;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Navigation\Page\Mvc;

class RegisterNavigationRouter extends AbstractHelper implements ServiceLocatorAwareInterface
{
    protected $serviceLocator;

    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
    {
        $this->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'
    )
),

这不是一个很好的解决方案,但它有效。

于 2014-07-29T15:44:03.307 回答