3

我正在努力Zend_Navigation使用动态 URL 参数实现面包屑。

简单的场景:想象一个CompanyController从URLviewAction()获取id参数以获取有关特定公司的信息的 a。

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

Desired breadcrumb: Home > Companies > [ Company name ]

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

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

  1. 如果每家公司有多个行动怎么办?

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

  2. 如果 URL 中有多个动态参数怎么办?

    对于每个company我们还需要管理它的contacts(公司所有者、财务官等),所以我们创建了一个ContactsController也持有一个viewAction和的editAction。由于联系人直接与公司相关联,因此我们希望在 URL 和面包屑中也反映这一点:

    URL: example.com/company/company-id/4/contacts/contact-id/2
    
    Desired breadcrumb: Home > Companies > [Company name] > Contacts of [Company name] > [Contact name]
    

    我们可以很容易地为此设置一条路线。id但是现在我们必须从 URL中获取多个。随着 URL 变得更加复杂,此过程可能更容易出错。

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

  1. 拉长Plugin_Navigation::preDispatch()钩子

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

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

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

我已经进行了大量研究,但似乎没有针对此问题的开箱即用解决方案。任何帮助将不胜感激。

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);
        }
    }
}

关于这个主题的一些参考资料:

4

1 回答 1

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

     }
}
于 2013-03-15T20:18:15.200 回答