在我的控制器中,我创建了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 \ View \ Helper \ Navigation \ AbstractHelper.php中没有组成Zend \ Mvc \ Router \ RouteStackInterface实例在第471行
但我在布局中使用的导航,因此它写在这里:http://adam.lundrigan.ca/2012/07/quick-and-dirty-zf2-zend-navigation/有效。我的错是什么?
谢谢。
答案 0 :(得分:9)
问题是缺少路由器(或者更准确地说,是Zend\Mvc\Router\RouteStackInterface
)。路由堆栈是路由的集合,可以使用路由名称将其转换为URL。基本上它接受一个路由名称并为你创建一个URL:
$url = $routeStack->assemble('my/route');
这也发生在Zend\Navigation
的MVC页面内。该页面有一个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
)的路线。
第二步
工厂会将其转换为导航对象结构,您需要先为其创建一个类。在MyModule / Navigation / Service目录中创建文件SecondaryNavigationFactory.php
。
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
答案 1 :(得分:1)
顺便说一句。如果定义controller
,则无需定义action
和route
,前提是您的路由是通用的,而控制器/操作是可变段。
答案 2 :(得分: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'
)
),
这不是一个很好的解决方案,但它确实有效。