如何在使用基本控制器时在preDispatch或init操作中处理Zend_Exception?

时间:2010-09-23 01:19:51

标签: zend-framework exception-handling

Zend Framework manual中所述,我创建了一个基本控制器。

  

对动作控制器进行子类化

     

按照设计,Zend_Controller_Action必须   被分类以创建一个   动作控制器。至少,你   将需要定义行动方法   控制器可以打电话。

     

除了创建有用的功能   对于您的Web应用程序,您可以   也发现你重复了很多   相同的设置或实用方法   在你的各种控制器;如果是这样,   创建一个公共基本控制器   扩展的类   Zend_Controller_Action可以解决   这种冗余。

但事实证明,Exceptions没有从基地正确调用...要复制它,请创建一个文件:

/path/to/workspace/library/Joe/Controller.php

然后:

class Joe_Controller extends Zend_Controller_Action
{
    public function init()
    {
        Throw new Zend_Exception('test', 500);
        parent::init();
    }
}

然后在您的控制器目录中,IndexController.php扩展到基数:

class IndexController extends Joe_Controller
{

您会发现该例外未被捕获。

但是,如果不延伸基本控制器,则在init或preDispatch中抛出异常,它将被捕获并转发到ErrorController。

任何人都知道如何从基本控制器中获取异常?

感谢。

更新以解决这个问题

在查看了有关如何构建目录的各种文章和官方文档后,我将基本控制器放在库/ Joe / ...中,但也许这是问题的一部分...手册中没有指导关于如何命名和放置基本控制器。有基础控制器的专家做了什么?

另一次更新

再看一下我的代码,并在网上阅读,似乎人们建议应该是:

抽象类Joe_Controller_Action扩展了Zend_Controller_Action。

除了改变它没有解决问题......

现在考虑有文章建议使用基本控制器,包括手册,这会被认为是Zend Framework中的错误吗?

要复制,只需在基本init或preDispatch中抛出任何类型的Zend_Exception。想象一下你在那里轮询数据库,(我正在做的事情)......数据库已关闭。没有错误控制器。除非我做错了事,否则这不是一个好的情况。

我怀疑这是一个新的错误......我不记得Zend_Application之前的这个问题,而且自从ZF 1.5以来我一直在使用基本控制器。

3 个答案:

答案 0 :(得分:0)

我头脑中有两个想法:

  1. 默认模块中的控制器名称通常命名为SomethingController。您的姓名Joe_Controller建议使用模块Joe控制器名称。

  2. 在路由/发送中,在发送到控制器之前,它不会查找匹配的操作吗?由于样本没有动作,您可能会触发ControllerNotFound异常吗?

  3. 只是抛出一些想法。

答案 1 :(得分:0)

在Zend哲学中,他们提供了init()方法以避免麻烦

public class Module_TotoController extends Zend_Action_Controller {

    public function __construct(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, array $invokeArgs = array())
        parent::__construct($request, $response, invokeArgs);

        // some init code here
    }
}

只需使用:

public class Module_TotoController extends Zend_Action_Controller {

    public function init ()
        // some init code here
    }
}

现在,如果您查看Zend_Controller_Action类来源,您会注意到以下方法为空

  • init()
  • preDispatch ()
  • postDispatch ()

这意味着,在您的特定控制器中调用 parent:: 是没用的

public class Module_TotoController extends Zend_Action_Controller {

    public function init ()
        parent::init(); // useless ;-) but you can go for it 

        // some init code here
    }
}

现在,如果您想在Module_TotoControllerZend_Action_Controller之间放置一个中间类,那么您将面临一个很大的麻烦:

  • 某些控制器不会扩展您的“基础”控制器(例如您的问题中的ErrorController)
    • 所以它不是你应用程序的真正基础,是吗?
  • 如果你在你的“base”的init()中添加一些逻辑,
    • 您必须致电parent::
    • 中的init()
    • 项目中的所有开发人员都需要了解
  • 您将为“Base”控制器添加另一些小功能
    • 这将导致一个庞大的文件
    • 加载/初始化那些lambda控制器中可能不需要的东西
      • 您是否在每个页面都需要数据库?
        • 否:$this->_helper->connect();看起来不是很好吗?
        • 是:使用控制器插件
  • 此“基础”控制器不适合您的其他项目需求,因此该类将无法重复使用
    • 动作助手将
    • 控制器插件

希望它有意义

答案 2 :(得分:-1)

不要去基地或任何控制器

正如文件所说:

  

按照设计,必须对Zend_Controller_Action进行子类化以创建动作控制器。

同意,这是误导 他们的意思是

class Module_TotoController extends Zend_Controller_Action {}

class Module_TotoController extends Joe_Controller是完全错误的(抱歉没有冒犯)

正如您所说,ErrorController无法扩展您的中级Joe_Controller课程 因为你的异常将在ErrorController类的实例化中被再次抛出(如例外!!!)

uncaught Exception错误是避免循环的保护结果(挖掘Zend\Controller\Plugin\ErrorHanlder.php行200-ish)

如果您需要为每个操作执行某些操作,请使用Zend_Controller_Plugin并将其注册到frontController