ZF2 - 将页面添加到控制器中的导航

时间:2014-01-15 15:25:41

标签: zend-framework2

在我的项目中,我有一个导航,它是使用默认工厂从config.php文件中的数组创建的。我想将子页面添加到控制器中的当前页面。

class IndexController extends AbstractActionController {
    public function newpageAction() {
        $navigation = $this->getServiceLocator()->get('navigation');
        $currentPage = $navigation->findById('index');

        $options = array(
            'id'         => 'newpage',
            'label'      => 'New Page',
            'route'      => 'my-route',
            'controller' => 'index',
            'action'     => 'newpage',
            'active'     => true,
        );
        $newpage = new \Zend\Navigation\Page\Mvc($options);

        $currentPage->addPage($newpage);
    }
}

页面添加成功但我尝试使用页面的getHref()方法在面包屑视图中为页面创建URL:

<?php foreach($this->pages as $page) {?>
<li>
    <a href="<?php echo $page->getHref();?>"><?php echo $page->getLabel();?></a>
</li>
<?php }?>

但是我为新添加的页面收到以下错误:

Additional information:
Zend\Navigation\Exception\DomainException

File:
\vendor\zendframework\zendframework\library\Zend\Navigation\Page\Mvc.php:198

Message:

Zend\Navigation\Page\Mvc::getHref cannot execute as no Zend\Mvc\Router\RouteStackInterface instance is composed

我想问题就在于我创建并将页面添加到导航的方式。还有另一种方法可以解决这个错误吗?

我想在控制器中而不是在配置文件中添加第3级之后的页面,因为页面的网址中有参数并且标签是动态的。 欢迎以任何其他方式完成此任务的任何建议。

3 个答案:

答案 0 :(得分:4)

您可以添加默认路由器。

\Zend\Navigation\Page\Mvc::setDefaultRouter ($this->getServiceLocator ()->get ('router'));

答案 1 :(得分:2)

错误是由于MVC页面具有未满足的依赖项(路由器)。它是the factory's job to inject these components(取决于URI或MVC类型)。

要确保每个MVC页面都注册了路由器,请创建新工厂,然后使用另一个已提供的工厂Zend\Navigation\Service\ConstructedNavigationFactory创建自己的导航容器并返回其页面。在您的示例中,这将只是一个页面。


修改

如果你 在控制器中添加导航页面,那么你不知道newpageAction()之前的页面配置;您可以扩展该类以允许在控制器中设置配置。

例如

public function MyCustomNavFactory extends ConstructedNavigationFactory
{
  // make the config optional
  public function __construct($config = array())
  {
    $this->config = $config;
  }
  // Allow config to be set outside the class
  public function setConfig($config)
  {
    $this->config = $config;
  }

}

<强> Module.php

// Module
public function getServiceConfig() {
  return array(
    'invokables' => array(
      // Create the factory as an invokable (as there are no __construct args)
      'MyCustomNavFactory' => 'App\Navigation\Service\MyCustomNavFactory'
    ),
  );
}

控制器调用只是简单地使用

// Controller
public function newpageAction()
{
  $serviceManager = $this->getServiceLocator();
  $navigation = $serviceManager->get('MyCustomNavFactory');

  $options = array(
    'id'         => 'newpage',
    'label'      => 'New Page',
    'route'      => 'my-route',
    'controller' => 'index',
    'action'     => 'newpage',
    'active'     => true,
  );
  $navigation->setConfig($options);
  $pages = $navigation->getPages($serviceManager);
}

答案 2 :(得分:0)

answer@AlexP是正确的。

但是控制器操作中出现错误当他使用ServiceLocator调用自定义工厂时,将获取类型为AbstractContainer的对象,因为ServiceLocator将调用{{1}自定义工厂(createService)扩展AbstractNavigationFactory的方法所以下一行会将MyCustomNavFactory方法调用setConfig对象而不是自定义工厂({{1} })。

从Controller Action设置Breadcrumb配置的正确方法是:

AbstractContainer

删除MyCustomNavFactory方法表单自定义工厂并使用它的构造函数设置配置

// Controller
public function newpageAction()
{
  $serviceManager    = $this->getServiceLocator();
  $navigationFactory = new MyCustomNavFactory();

  $options = array(
    'id'         => 'newpage',
    'label'      => 'New Page',
    'route'      => 'my-route',
    'controller' => 'index',
    'action'     => 'newpage',
    'active'     => true,
  );
  $navigationFactory->setConfig($options);
  $pages = $navigationFactory->getPages($serviceManager);
}

然后控制器将是:

setConfig