Zend framework2 ZF2-向控制器中的导航添加页面

Zend framework2 ZF2-向控制器中的导航添加页面,zend-framework2,Zend Framework2,在我的项目中,我有一个导航,它是使用默认工厂从config.php文件中的数组创建的。我想将子页面添加到控制器中的当前页面 class IndexController extends AbstractActionController { public function newpageAction() { $navigation = $this->getServiceLocator()->get('navigation'); $currentPa

在我的项目中,我有一个导航,它是使用默认工厂从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()方法在breadcrumbs视图中创建页面的url:

<?php foreach($this->pages as $page) {?>
<li>
    <a href="<?php echo $page->getHref();?>"><?php echo $page->getLabel();?></a>
</li>
<?php }?>
我想问题在于我创建页面并将其添加到导航中的方式。是否有其他方法可以做到这一点,或者如何修复此错误

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

您可以添加默认路由器

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

您可以添加默认路由器

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

该错误是由于
MVC
页面具有未满足的依赖项(路由器)造成的。它是(取决于URI或MVC类型)

为了确保每个MVC页面都已创建一个新的工厂,该工厂反过来使用另一个已提供的工厂来创建您自己的导航容器并返回其页面。在您的示例中,这将只是一页


编辑

如果必须在控制器中添加导航页面,在
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);
}

该错误是由于
MVC
页面具有未满足的依赖项(路由器)造成的。它是(取决于URI或MVC类型)

为了确保每个MVC页面都已创建一个新的工厂,该工厂反过来使用另一个已提供的工厂来创建您自己的导航容器并返回其页面。在您的示例中,这将只是一页


编辑

如果必须在控制器中添加导航页面,在
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);
}
这个公式是正确的

但是控制器操作中出现错误,因为当他使用
ServiceLocator
调用自定义工厂时,将获取Object类型的对象,因为
ServiceLocator
将调用
createService
方法到您的自定义工厂(
MyCustomNavFactory
)扩展后,下一行将调用
setConfig
方法到
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
方法,并使用其构造函数设置配置

// custom Factory
public function MyCustomNavFactory extends ConstructedNavigationFactory
{
  // make the config optional
  public function __construct($config = array())
  {
    parent::__construct($config);
  }
} 
那么控制器将是:

// Controller
public function newpageAction()
{
  $serviceManager = $this->getServiceLocator();    
  $options = array(
     array(
       'id'         => 'newpage',
       'label'      => 'New Page',
       'route'      => 'my-route',
       'controller' => 'index',
       'action'     => 'newpage',
       'active'     => true,
    )
  );
  $navigationFactory = new MyCustomNavFactory($options);
  $pages = $navigationFactory->getPages($serviceManager);
}
这个公式是正确的

但是控制器操作中出现错误,因为当他使用
ServiceLocator
调用自定义工厂时,将获取Object类型的对象,因为
ServiceLocator
将调用
createService
方法到您的自定义工厂(
MyCustomNavFactory
)扩展后,下一行将调用
setConfig
方法到
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
方法,并使用其构造函数设置配置

// custom Factory
public function MyCustomNavFactory extends ConstructedNavigationFactory
{
  // make the config optional
  public function __construct($config = array())
  {
    parent::__construct($config);
  }
} 
那么控制器将是:

// Controller
public function newpageAction()
{
  $serviceManager = $this->getServiceLocator();    
  $options = array(
     array(
       'id'         => 'newpage',
       'label'      => 'New Page',
       'route'      => 'my-route',
       'controller' => 'index',
       'action'     => 'newpage',
       'active'     => true,
    )
  );
  $navigationFactory = new MyCustomNavFactory($options);
  $pages = $navigationFactory->getPages($serviceManager);
}

谢谢你的回答。现在我明白了为什么url生成不起作用了。但是在您的解决方案中,页面的$options在工厂中,如果我想创建其他自定义页面,我想应该创建另一个工厂。是否有其他方法为每个自定义页面提供$options。我想,我可以在控制器操作中直接使用ConstructedNavigationFactory,或者这是一个糟糕的设计?@ElenaSlavcheva我已经更新了我的答案-在控制器操作之前不知道
$options
将改变方法。我确信有一个“更干净”的解决方案(比如将控制器中的上述代码移动到服务层);我个人希望配置中的所有“新页面”都在某个地方,并且每个不同的“新页面”都有一个工厂,这样可以避免可能的代码重复。谢谢AlexP的回答。现在我明白了为什么url生成不起作用了。但是在您的解决方案中,页面的$options在工厂中,如果我想创建其他自定义页面,我想应该创建另一个工厂。是否有其他方法为每个自定义页面提供$options。我想,我可以在控制器操作中直接使用ConstructedNavigationFactory,或者这是一个糟糕的设计?@ElenaSlavcheva我已经更新了我的答案-在控制器操作之前不知道
$options
将改变方法。我确信有一个“更干净”的解决方案(比如将控制器中的上述代码移动到服务层);我个人希望配置中的所有“新页面”都在某个地方,并且每个不同的“新页面”都有一个工厂,这样可以避免可能的代码重复。谢谢akond!工作很有魅力,谢谢你,阿康!工作得很有魅力。