0

我目前正在阅读“Keith Pope”撰写的“Zend Framework 1.8 Web Application Development”。他告诉我们使用“ActionStack”,以便在每次请求时都会调用类别顶级菜单的控制器。该插件的源代码是:

class SF_Plugin_Action extends Zend_Controller_Plugin_Abstract 
{
    protected $_stack;

    public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request) 
    {
      $stack = $this->getStack();

      // category menu
      $categoryRequest = new Zend_Controller_Request_Simple();
      $categoryRequest->setControllerName('category')
                      ->setActionName('index')
                      ->setParam(
                          'responseSegment', 
                          'categoryMain'
                      );

      // push requests into the stack
      $stack->pushStack($categoryRequest);
    }

    public function getStack()
    {
      if (null === $this->_stack) {
        $front = Zend_Controller_Front::getInstance();

        if (!$front->hasPlugin(
          'Zend_Controller_Plugin_ActionStack'
        )) {
           $stack = new Zend_Controller_Plugin_ActionStack();
           $front->registerPlugin($stack);
        } else {
           $stack = $front->getPlugin('ActionStack');
        }

        $this->_stack = $stack;
    }

    return $this->_stack;
  }
}

我已经阅读了“ActionStack”插件的代码。在“postDispatch”函数中,它保存当前请求,然后在“转发”函数中,它更改当前请求的控制器、操作并设置参数。那么当前请求会发生什么?它将如何执行?

我还听说ActionStack 是邪恶的。由于我是新手,我大部分都不懂,因为他没有解释(对于新手)。为什么 ActionStack 是邪恶的?

4

3 回答 3

3

ActionStack 是邪恶的,因为它提倡一种不好的做法:将视图相关的逻辑绑定到控制器。此外,它对性能有巨大的负面影响。

通常,ActionStack 用于开发“widgetized”站点。您设置所需的小部件列表,并将它们映射到各个控制器操作,然后循环遍历堆栈。这样做的设计缺陷是您现在正在执行 N 个不同的控制器——实际上,您应该只使用一个控制器。每个单独的控制器都应该能够将传入的请求映射到必要的视图和模型。相反,您现在基本上只是为了取回一些内容而执行 MVC 三元组。

性能影响来自这样一个事实,即您现在必须将以前的结果存储在内存中,然后重新分派——这意味着再次运行所有前/后分派插件,可能会出现状态冲突等等。

更好的方法是拥有模型感知视图助手。您可以使用动作助手来编组适当的模型并注入助手,然后在您的视图脚本和/或布局中,您只需调用它们。这尊重了适当的关注点分离,并且没有相同的性能影响。

(在 ZF2 中,这种编组要容易得多,因为您可以为各个帮助程序定义工厂——因此,您可以简单地在视图脚本中使用它们,而无需在控制器中执行任何特殊操作即可交付小部件内容。)

于 2012-10-15T14:17:29.387 回答
0

这是我第一个问题的答案。由于动作堆栈将最后执行(在 post dispatch 中),当前响应对象将保存为用户发出的请求而呈现的所有内容,并且动作堆栈会将数据附加到它。因此,用户将获得他要求的内容+由于操作堆栈而呈现的内容

于 2012-10-25T03:38:34.500 回答
0

在你的例子中。前端控制器将开始执行当前请求并触发 routeStartup、routeShutdown 和 dispatchLoopStartup 事件。dispatchLoopStartup 事件将调用您的插件,并且您的插件会将请求对象添加到操作堆栈。

现在前端控制器将分发当前请求,将当前请求的 isDispatched 标志设置为 true 并触发 postDispatch 事件。现在将调用动作堆栈插件。前端控制器将当前请求对象作为参数传递给动作堆栈插件,动作堆栈插件将更新当前请求对象的控制器、模块、动作属性并将其 isDispatched 标志设置为 false(转发方法)。

现在前端控制器将检查当前请求对象的 isDispatched 标志,并且由于它被 Action Stack 插件重置,因此再次启动调度过程。现在您的新请求将被执行。

简而言之,前端控制器调度当前请求,动作堆栈插件重置当前请求的值,调度循环再次启动。

于 2013-08-13T05:14:10.750 回答