Zend framework2 ZF2-在调用控制器之前向导航注入页面

Zend framework2 ZF2-在调用控制器之前向导航注入页面,zend-framework2,zend-route,zend-navigation,zend-config,Zend Framework2,Zend Route,Zend Navigation,Zend Config,我正在创建一个动态应用程序,其中的内容是通过CMS添加的。在CMS中,我设置了一个db条目,该条目说明每个内容页使用哪个模块 诺代德, 父节点ID, 姓名(德), 姓名(u en), 模块名称, foreignkey_内容链接 此表中的条目如下所示: 6. 1. Veranstaltung-21-02-2013, 事件-21-02-2013, 事件, 682 整个树应该在我的导航中结束(也完全在我的路由中)。我不想把它添加到某个控制器中,因为我的应用程序由一大堆模块组成,我想在所有模块中访问这些

我正在创建一个动态应用程序,其中的内容是通过CMS添加的。在CMS中,我设置了一个db条目,该条目说明每个内容页使用哪个模块

诺代德, 父节点ID, 姓名(德), 姓名(u en), 模块名称, foreignkey_内容链接

此表中的条目如下所示: 6. 1. Veranstaltung-21-02-2013, 事件-21-02-2013, 事件, 682

整个树应该在我的导航中结束(也完全在我的路由中)。我不想把它添加到某个控制器中,因为我的应用程序由一大堆模块组成,我想在所有模块中访问这些信息

我已经尝试将其注入global.php中,但没有效果,因为在那个阶段我无法使用我的db适配器或任何其他重要类


是否有指向最佳实践的想法或链接?

导航容器由工厂类组成。最简单的方法是编写自己的工厂,并使用
getPages()
方法从数据库而不是从配置中获取页面。如果从AbstractNavigationFactory进行扩展,则只需编写几个方法

<?php
namespace Application\Navigation\Service;

use Zend\Navigation\Service\AbstractNavigationFactory;
use Zend\ServiceManager\ServiceLocatorInterface;

class CmsNavigationFactory extends AbstractNavigationFactory
{
    /**
     * @param ServiceLocatorInterface $serviceLocator
     * @return array
     * @throws \Zend\Navigation\Exception\InvalidArgumentException
     */
    protected function getPages(ServiceLocatorInterface $serviceLocator)
    {
        if (null === $this->pages) {

            $application = $serviceLocator->get('Application');
            $routeMatch  = $application->getMvcEvent()->getRouteMatch();
            $router      = $application->getMvcEvent()->getRouter();

            // get your pages from wherever...
            $pages       = $this->getPagesFromDB();

            $this->pages = $this->injectComponents($pages, $routeMatch, $router);
        }
        return $this->pages;
    }

    public function getName()
    { 
         // this isn't used if fetching from db, it's just here to keep the abstract factory happy
         return 'cms';
    }
}
并以相同的方式将其与导航视图帮助器一起使用

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

回应您对@Crisp答案的评论,对于未来的谷歌用户,我将解释如何为路由做类似的事情

通常,您希望创建一个自定义路由器,该路由器可以将URL与数据库中的页面相匹配,类似于标准的
路由器。为此,您必须实现
Zend\Mvc\Router\RouteInterface
接口。例如:

namespace Application\Router;

use Zend\Mvc\Router\RouteInterface;
use Application\Model\CMSTable;

class CmsRoute implements RouteInterface, ServiceLocatorAwareInterface
{
    protected $table;

    // Service locator injection code

    public function getCmsTable()
    {
        // Retrieve the table from the service manager
    }

    public function match(Request $request)
    {
        // Match the request on some route field, etc.
    }

    public function assemble(array $params = array(), array $options = array())
    {
        // Assemble a URL based on the given parameters (e.g. page ID).
    }

    public static function factory($options = array())
    {
        // Construct a new route, based on the options.
    }
}
然后,您可以将此路由注册为模块配置中的
RoutePluginManager
的可调用路由:

'route_manager' => array(
  'invokables' => array(
    'Cms' => 'Application\Router\CmsRoute'
  ),
),
然后,您可以使用类型
Cms
创建一个新路由(就像您创建任何其他路由一样)。路由插件管理器将创建路由实例,由于
CmsRoute
实现了
ServiceLocatorAwareInterface
,插件管理器将自己注入路由中。反过来,插件管理器设置了主服务管理器,因此您可以从那里获取数据库表


当然,您可以在页面ID上进行匹配,但如果您具有层次结构,则最好在URL中反映这一点。因此,我建议在数据库模式中添加一个
route
字段,并从树根开始向下匹配。

谢谢你!我想,我将以类似的方式从数据库中注入路由?谢谢!写入getPagesFromDB()方法的正确位置在哪里?
'route_manager' => array(
  'invokables' => array(
    'Cms' => 'Application\Router\CmsRoute'
  ),
),