views:

106

answers:

2

Hi

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 output 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");
    }
}
A: 

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

takeshin
Take a look at the last comment on that post - http://codeutopia.net/blog/2009/03/02/handling-errors-in-zend-framework/#comment-62592 - it is from me. :-) I am throwing the error in `preDispatch()` in my `Zend_Controller_Plugin_Abstract`
jakenoble
@jakenoble, Paste some code. When do you call `parent::preDispatch()`? Is `error_handler` already registered?
takeshin
@takeshin I think the error_handler is not registered. If I throw the Exception outside of a `try { }` statement in `preDispatch()` it does not get caught by the `ErrorController`. I haven't explicitly set the application to not register the error_handler. Do I need to explicitly load it in my `Bootstrap` class in order to make sure it is there for my Plug-in?
jakenoble
I think you may just have made the internet leak memory. ;)
Jani Hartikainen
@jakenoble, Why don't you just paste the complete code which does not work? set `error_reporting(-1)` and see what is going on.
takeshin
@takeshin Some code snippets added, I haven't pasted in my exact code because most of it does not effect the issue here.
jakenoble
+1  A: 

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.

Jani Hartikainen
@jani that all makes sense. I think I would rather redirect the user and handle it that way. Rather than creating a plug-in to catch an Exception in other plug-ins - could end up confusing me more!
jakenoble
I marked this as the answer because you can't seem to do what I want, but this is the closest to getting there.
jakenoble