带动态URL参数的Zend_Navigation

时间:2012-12-13 15:15:02

标签: zend-framework zend-navigation

我很难用动态网址参数实现Zend_Navigation面包屑。

简单方案:想象一下CompanyController viewAction()的{​​{1}}从网址获取id参数,以获取有关特定公司的信息。

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

Desired breadcrumb: Home > Companies > [ Company name ]

我已经在线进行了一些研究,并提出了以下解决方案:在predispatch()挂钩中,我从id获取$_SERVER['REQUEST_URI']参数(我们无法使用请求对象)为此,因为调度还没有开始)并从数据库中获取该记录。然后我只需将此页面添加到Zend_Navigation容器中的根页面。你可以在这篇文章的底部看到它的实现。

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

  1. 如果每个公司有多个操作,该怎么办?

    view公司记录外,我们可能还想editexample.com/company/edit/id/4)或对其执行其他操作。当然,我们可以创建一个switch语句来检查URL中的操作,但我觉得这不可扩展。

  2. 如果网址中有多个动态参数,该怎么办?

    对于每个company,我们还需要管理其contacts(公司所有者,财务官等),以便我们创建一个ContactsController,其中还包含viewActioneditAction。由于联系人直接与公司绑定,我们希望将其反映在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变得越来越复杂,这个过程会更容易出错。

  3. 到目前为止,我已经提出了两个看似合理的解决方案:

    1. 扩展Plugin_Navigation::preDispatch()挂钩

      可能的解决方案是使用详细的URL参数(如company-idcontact-id)。这样我们就可以提取名称(即company)并通过相应的模型类获取记录。

    2. 在我们的操作方法

      中将页面添加到导航容器中

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

    3. 我做了大量的研究,但似乎没有针对这个问题的开箱即用的解决方案。非常感谢任何帮助。

      前面提到的Plugin_Navigation::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);
              }
          }
      }
      

      有关此主题的一些参考资料:

1 个答案:

答案 0 :(得分:0)

您可以通过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

     }
}