2

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

NodeId、ParentNodeId、Name_de、Name_en、ModuleName、foreignkey_ContentLinks、

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

整个树应该最终出现在我的导航中(并且完美地出现在我的路由中)。我不想将它添加到某个控制器中,因为我的应用程序由一大堆模块组成,我想在我的所有模块中访问该信息。

我已经尝试在 global.php 中注入它,但无济于事,因为在那个阶段我不能使用我的数据库适配器或任何其他重要的类。

任何想法或最佳实践链接?

4

2 回答 2

5

导航容器由工厂类组成。最简单的方法是编写自己的工厂并让该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';
    }
}

将工厂添加到服务管理器中,就像添加其他容器一样

'service_manager' => array(
    'factories' => array(
        'CmsNavigation' => 'Application\Navigation\Service\CmsNavigationFactory',
    ),
),

并以相同的方式将其与导航视图助手一起使用

<?php echo $this->navigation()->menu('CmsNavigation'); ?>
于 2013-05-18T08:57:24.967 回答
0

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

通常,您会希望创建一个自定义路由器,该路由器可以将 URL 与数据库中的页面相匹配,类似于标准Segment路由器。为此,您必须实现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'
  ),
),

然后,您可以使用 type 创建一条新路线(就像您为任何其他路线所做的那样)Cms。路由插件管理器将创建您的路由实例,并且由于CmsRouteimplements ServiceLocatorAwareInterface,插件管理器将自己注入到路由中。反过来,插件管理器具有主服务管理器集,因此您可以从那里获取数据库表!

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

于 2014-03-25T03:18:26.507 回答