Handling Exceptions thrown in Zend Framework's Controller Plugins
I have an Acl plug-in which extends Zend_Controller_Plugin_Abstract
, this plug-in handles all my Acl code.
I want to thrown an Exception in this plug-in, e.g. an Exception_Unauthorised
and then handle this in my ErrorController
, this way I can use the same Acl plug-in for different applications and use the ErrorController
to handle each situation in each application differently - if need be.
The problem is that throwing an Exception in the plug-in does not stop the original Action from executing. So I end up with the original Action's outpu开发者_开发百科t and the ErrorController
output.
How can I get an Exception thrown in a plug-in to stop the original Action from taking place?
Case 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");
}
Case 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)
{
}
}
Case 3
I think this is where the issue is, by changing the controller.
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");
}
}
Take a look at this article: http://akrabat.com/zend-framework/handling-exceptions-in-a-front-controller-plugin/
I had a quick chat about this on the #zftalk IRC channel, and Ryan Mauger / Bittarman said that currently you would need to manually redirect the user if the exception happens in a plugin.
I also had an idea that maybe you could use a separate plugin to check for an exception. If you look at the ErrorHandler plugin, it checks if the request contains an exception and acts on it.
The problem is that the ErrorHandler fires on routeShutdown, eg. when the request has already finished. If you created a custom plugin which looks at the exception, but runs on preDispatch, it might be possible to automate this task.
Note that you would need to make sure this custom plugin is ran after any plugins that may throw exceptions.
This should work. It all depends, when or where you throw the exception. Take a look at this blog post:
Handling errors in Zend Framework | CodeUtopia - The blog of Jani Hartikainen
This is what I do.
// 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);
精彩评论