Zend framework 带有动态URL参数的Zend_导航

Zend framework 带有动态URL参数的Zend_导航,zend-framework,zend-navigation,Zend Framework,Zend Navigation,我正在努力用动态URL参数实现Zend_导航breadcrumbs 简单的场景:想象一个CompanyController和一个viewAction()从URL获取id参数以获取特定公司的信息 URL: example.com/company/view/id/4 Desired breadcrumb: Home > Companies > [ Company name ] 我在网上做了一些研究,并提出了以下解决方案:在predispatch()钩子中,我从$\u服务器['REQU

我正在努力用动态URL参数实现
Zend_导航
breadcrumbs

简单的场景:想象一个
CompanyController
和一个
viewAction()
从URL获取
id
参数以获取特定公司的信息

URL: example.com/company/view/id/4

Desired breadcrumb: Home > Companies > [ Company name ]
我在网上做了一些研究,并提出了以下解决方案:在
predispatch()
钩子中,我从
$\u服务器['REQUEST\u URI']
获取
id
参数(由于调度尚未开始,我们无法使用REQUEST对象),然后从数据库中获取该记录。然后,我只需将此页面添加到
Zend_导航
容器中的根页面。你可以在这篇文章的底部看到它的实现

我发现这种方法的问题在于它不可扩展:

  • 如果每家公司都有一个以上的行动怎么办

    除了查看公司记录外,我们可能还希望编辑公司记录(
    example.com/company/edit/id/4)或对其执行其他操作。当然,我们可以创建一个switch语句来检查URL中的操作,但我觉得这是不可伸缩的

  • 如果URL中有多个动态参数怎么办

    对于每个
    公司
    我们还需要管理其
    联系人
    (公司所有者、财务官等),因此我们创建了一个
    联系人控制器
    ,它还包含一个
    视图动作
    编辑动作
    。由于联系人直接与公司关联,因此我们希望在URL和面包屑中也反映这一点:

    URL: example.com/company/company-id/4/contacts/contact-id/2
    
    Desired breadcrumb: Home > Companies > [Company name] > Contacts of [Company name] > [Contact name]
    
    我们可以很容易地为此设置路线。但是现在我们必须从URL中获取多个
    id
    。随着URL变得越来越复杂,此过程可能更容易出错

  • 到目前为止,我已经提出了两个可行的解决方案:

    class Plugin_Navigation extends Zend_Controller_Plugin_Abstract
    {
        public function preDispatch()
        {
            $view       = Zend_Controller_Action_HelperBroker::getExistingHelper('ViewRenderer')->view;
            $config     = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.xml','nav');
            $container  = new Zend_Navigation($config);
    
            $urlParts   = explode('/', ltrim($_SERVER['REQUEST_URI'], '/'));
            $pos        = array_search('id', $urlParts);
    
            if ($pos !== FALSE)
            {
                $id         = $urlParts[$pos + 1];
    
                $model      = new Model_Company();
                $company    = $model->fetchOne($id);
    
                $rootPage   = $container->findOneBy('controller', 'company');
    
                $rootPage->addPage(new Zend_Navigation_Page_Mvc(array(
                        'controller' => 'company',
                        'action'     => 'view',
                        'label'      => $company->name
                    )));
    
                $view->navigation($container);
            }
        }
    }
    
  • 扩展
    插件导航::preDispatch()
    钩子

    一个可能的解决方案是使用详细的URL参数(如
    公司id
    联系人id
    )。通过这种方式,我们可以提取名称(即
    公司
    ),并通过相应的模型类获取记录

  • 在我们的操作方法中将页面添加到导航容器中

    我认为这是最灵活的选择,但也意味着我们不能再从一个中心点管理面包屑了,这是一个严重的缺点

  • 我做了大量的研究,但似乎没有现成的解决方案。任何帮助都将不胜感激

    前面提到的
    插件导航::preDispatch()
    钩子:

    class Plugin_Navigation extends Zend_Controller_Plugin_Abstract
    {
        public function preDispatch()
        {
            $view       = Zend_Controller_Action_HelperBroker::getExistingHelper('ViewRenderer')->view;
            $config     = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.xml','nav');
            $container  = new Zend_Navigation($config);
    
            $urlParts   = explode('/', ltrim($_SERVER['REQUEST_URI'], '/'));
            $pos        = array_search('id', $urlParts);
    
            if ($pos !== FALSE)
            {
                $id         = $urlParts[$pos + 1];
    
                $model      = new Model_Company();
                $company    = $model->fetchOne($id);
    
                $rootPage   = $container->findOneBy('controller', 'company');
    
                $rootPage->addPage(new Zend_Navigation_Page_Mvc(array(
                        'controller' => 'company',
                        'action'     => 'view',
                        'label'      => $company->name
                    )));
    
                $view->navigation($container);
            }
        }
    }
    
    有关此主题的一些参考资料:

    class Plugin_Navigation extends Zend_Controller_Plugin_Abstract
    {
        public function preDispatch()
        {
            $view       = Zend_Controller_Action_HelperBroker::getExistingHelper('ViewRenderer')->view;
            $config     = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.xml','nav');
            $container  = new Zend_Navigation($config);
    
            $urlParts   = explode('/', ltrim($_SERVER['REQUEST_URI'], '/'));
            $pos        = array_search('id', $urlParts);
    
            if ($pos !== FALSE)
            {
                $id         = $urlParts[$pos + 1];
    
                $model      = new Model_Company();
                $company    = $model->fetchOne($id);
    
                $rootPage   = $container->findOneBy('controller', 'company');
    
                $rootPage->addPage(new Zend_Navigation_Page_Mvc(array(
                        'controller' => 'company',
                        'action'     => 'view',
                        'label'      => $company->name
                    )));
    
                $view->navigation($container);
            }
        }
    }
    

    只需在bootstrap.php文件中引导前端控制器即可解决此问题

    在bootstrap.php文件中添加:

    public function _initRequest()
    {
        $this->bootstrap('frontController');
        $front = $this->getResource('frontController');
        $front->setRequest(new Zend_Controller_Request_Http());
    
        $request = $front->getRequest();
    }
    
    然后在插件中,在preDispatch函数中传递请求对象

    class Your_Controller_Plugin_PluginName extends Zend_Controller_Plugin_Abstract
    {
         public function preDispatch(Zend_Controller_Request_Abstract $request)
         {
               $MyController =$request->getControllerName();
               $MyAction     =$request->getActionName();
               $MyParams     =$request->getParams(); 
    
        //now you can go ahead with implementing your breadcrumb
    
         }
    }