ZF-2461: Throwing Exceptions within a plugins causes application failures

Description

I have written a small "TestPlugin" with the following code:

<?php
class TestPlugin extends Zend_controller_Plugin_Abstract
{
    public function routeStartup()
    {
    }

    public function dispatchLoopStartup()
    {
    }

    public function preDispatch()
    {
    }

    public function postDispatch()
    {
    }
}

Then I started to throw an exception in each method per request, to try out how Zend_Layout it handles. And now the failures begin: within routeStartup() and dispatchLoopStartup() the page get's rendered twice: the errorAction + the page I requested inside the "content" placeholder.

When an ecxeption is thrown within preDispatch() oder postDispatch(), I get the following exception:

Fatal error: Uncaught exception 'Zend_Exception' in /var/www/dlm/application/plugins/TestPlugin.php:16 Stack trace:

0 /var/www/library/Zend/Controller/Plugin/Broker.php(316): TestPlugin->preDispatch(Object(Zend_Controller_Request_Http))

1 /var/www/library/Zend/Controller/Front.php(914): Zend_Controller_Plugin_Broker->preDispatch(Object(Zend_Controller_Request_Http))

2 /var/www/public/index.php(37): Zend_Controller_Front->dispatch()

3 {main} thrown in /var/www/application/plugins/TestPlugin.php on line 16

Comments

Unsetting 'fix version priority' until this issue is reviewed. Assigning to Matthew for review.

This bug still exists - on zfforum.de another user has described the problem with doubled rendered layouts while an exception has occured (this does not happen on every exception). "mvcSuccessfulActionOnly" is "true"! I use ZF Version 1.5.1 at the moment.

Assigning to Ralph to evaluate.

Updating project management info.

I have found an solution. I set "mvcSuccessfulActionOnly" to "false" and called in the errorAction() of the ErrorController "$this->getResponse()->clearBody();"

This works not only in controller-actions, it also works well with Exceptions thrown in Plugins!

So this is a non issue now? I assume you might have found this issue before mvcSuccessfulActionOnly was implemented.

Can i close as non-an-issue?

-Ralph

Updating for the 1.6.0 release.

I'm not sure that "resolved" is adequate ATM, given the information above.

Using ZF 1.9.5 I am seeing this issue when a front controller plugin throws an exception during preDispatch(), and at least one problem with this "resolution" is that the originally requested action still runs and the issue is worked around in the error controller.

I am not using mvcSuccessfulActionOnly because I'm using the ContextSwitch helper for an XML response.

It appears that throwing an exception in preDispatch() is pointless because the action runs anyway. To handle the exception immediately the plugin needs to redirect the request to the error handler. Alternately you can exit Zend_Controller_Plugin_Broker::preDispatch() with an error if you set Zend_Controller_Front::throwExceptions to true, but then in dispatch() of the FrontController you don't get a chance to handle the exception because the exception is thrown again (because of throwExceptions!).

Given this situation it might be useful to have a helper method for plugins to alter the request to send it to the error controller, much the same was as in postDispatch() of the ErrorHandler plugin. This helper method could then be used in preDispatch() of other plugins (instead of throwing exceptions), or the whole plugin preDispatch() error handling situation could be reviewed.

There's also the possibility that I'm barking up the wrong tree and should NEVER throw an exception in a front controller plugin!

Could we please have comment on whether; a) throwing exceptions from front controller plugins is acceptable and what we should do instead if it's not, and b) running the originally requested action if an exception is thrown by a plugin during preDispatch is desirable/useful/acceptable

For basic context I have a plugin that is performing authentication (of the CAS variety) and if we have an issue upstream then I'd like to propagate it.

I'm asking myself the same questions as Andrew Sharpe is. And it's because of the same situation: I have a Controller Plugin (extending from {{Zend_Controller_Plugin_Abstract}}) that may throw an Exception in it's {{dispatchLoopStartup()}} method.

What I would like is that this Exception gets somehow handled by the {{Zend_Controller_Plugin_ErrorHandler}} (just like any Exception thrown from a {{Zend_Controller_Action}}) but : Asking the FrontController to throw exceptions results in a {{Exception}} displayed by PHP without going through ErrorHandler plugin. Otherwise (FrontController not throwing exceptions), the {{Exception}} gets added to {{Zend_Controller_Response_Http}} object by {{Zend_Controller_Plugin_Broker::dispatchLoopStartup()}}.

Should I need to create my own ErrorHandler Plugin that checks {{Zend_Controller_Response_Http}} object for any {{Exception}} and intercept them (forwarding to defined controller/action, e.g. "/error/error")?

PS: My plugin is also a plugin that deals with authentification (retrieving users informations from an LDAP server)