处理在Zend Framework的控制器插件中抛出的异常

5
我有一个扩展了Zend_Controller_Plugin_Abstract的Acl插件,它处理了我所有的Acl代码。
我想在这个插件中抛出一个异常,比如Exception_Unauthorised,然后在我的ErrorController中处理它,这样我可以为不同的应用程序使用相同的Acl插件,并在每个应用程序中使用ErrorController以不同的方式处理每种情况-如果需要的话。
问题是,在插件中抛出异常并不能阻止原始操作的执行。因此,我最终会得到原始操作的输出和ErrorController的输出。
如何使插件中抛出的异常能够停止原始操作的执行? 案例1
// This throws the `Exception_NoPermissions`, but it does not get caught by
// `ErrorController`
public function preDispatch(Zend_Controller_Request_Abstract $request)
{       
    parent::preDispatch($request);
    throw new Exception_NoPermissions("incorrect permissions");
}

案例2

// This behaves as expected and allows me to catch my Exception
public function preDispatch(Zend_Controller_Request_Abstract $request)
{       
    parent::preDispatch($request);
    try
    {
        throw new Exception_NoPermissions("incorrect permissions");
    }
    catch(Exception_NoPermissions $e)
    {

    }
}

案例三

我认为问题就出在这里,通过更改控制器解决。

public function preDispatch(Zend_Controller_Request_Abstract $request)
{       
    parent::preDispatch($request);

    // Attempt to log in the user

    // Check user against ACL

    if(!$loggedIn || !$access)
    {
        // set controller to login, doing this displays the ErrorController output and
        // the login controller
        $request->getControllerName("login");
    }
}
4个回答

5

4
我曾在#zftalk IRC频道上进行了简短的讨论,Ryan Mauger / Bittarman 表示目前如果插件出现异常,则需要手动重定向用户。
我还有一个想法,可能可以使用单独的插件来检查异常。如果您查看ErrorHandler插件,它会检查请求是否包含异常并对其进行操作。
问题是ErrorHandler在routeShutdown时触发,例如当请求已经完成时。如果您创建一个自定义插件来查看异常,但在preDispatch上运行,可能可以自动化此任务。
请注意,您需要确保此自定义插件在可能引发异常的任何插件之后运行。

那都有道理。我想我更愿意重定向用户并以这种方式处理它。而不是创建一个插件来捕获其他插件中的异常 - 这可能会让我更加困惑! - Jake N
我将此标记为答案,因为您似乎无法做到我想要的,但这是最接近实现目标的方法。 - Jake N

0

这就是我所做的。

// Get Request Object...
$request = $this->getRequest();
// Do manual redirect.. select your own action...
$this->getRequest()->setControllerName('error')->setActionName('could-not-find-destination')->setDispatched(true);
$error = new Zend_Controller_Plugin_ErrorHandler();
$error->type = Zend_Controller_Plugin_ErrorHandler::EXCEPTION_OTHER;
$error->request = clone( $request );
$error->exception = $e; // If you have caught the exception to $e, set it. 
$request->setParam('error_handler', $error);

0

看一下那篇文章的最后一条评论 - http://codeutopia.net/blog/2009/03/02/handling-errors-in-zend-framework/#comment-62592 - 那是我写的。:-)我在我的 Zend_Controller_Plugin_AbstractpreDispatch() 中抛出了错误。 - Jake N
@jakenoble,请粘贴一些代码。什么时候调用parent::preDispatch()error_handler已经注册了吗? - takeshin
@takeshin,我认为error_handler没有注册。如果我在preDispatch()中的try { }语句之外抛出异常,则不会被ErrorController捕获。我没有明确设置应用程序不注册error_handler。我需要在我的Bootstrap类中显式加载它以确保插件中存在吗? - Jake N
2
我想你可能刚刚让互联网泄露了内存。 ;) - Jani Hartikainen
@jakenoble,为什么不直接粘贴完整的代码呢?设置error_reporting(-1)并查看发生了什么。 - takeshin
@takeshin,我添加了一些代码片段,但我没有粘贴我的确切代码,因为大部分代码对此问题没有影响。 - Jake N

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接