Steve Clay
Steve Clay

Reputation: 8781

Can I cancel a Zend Controller action in the init() method?

During Zend_Controller_Action::init(), is there a way to cancel the action (so it won't be called)?

<?php
class JsonApiController extends Zend_Controller_Action {
    function init()
    {
        // try JSON decoding the raw request body
        if ($jsonDecodingFailed) {
            echo '{"error":"invalid JSON"}';
            $this->_cancelAction(); // something like this exist?
        }
    }
}

My current workaround is to make an empty nullAction() method and call $this->_forward('null') to forward to it.

Upvotes: 6

Views: 4950

Answers (5)

FDIM
FDIM

Reputation: 1989

For someone that is still looking for solution you can try this: Add a flag stating whether there is an error or not and override dispatch method. If the flag is set, do not invoke parent::dispatch.

This works the way I want it to. My reason was that I am making an abstract API controller, which by default checks for an API key in request, if its not there - controller should respond with error and complete request successfully.

E.g.

abstract class Api_Controller extends Zend_Rest_Controller{
 private $responded = false;
 public function init() {
    parent::init();
    if(!$this->isKeyValid())
       $this->respond("invalid key"); // this would set flag to true and handle error
 }
 public function dispatch($action) {
    // if an error occured and it was dispatched, do not call action method, just finish request
    if(!$this->responded)
        parent::dispatch($action);
 }
}

For me this seems like a clean solution.

Upvotes: 1

mouadkrt
mouadkrt

Reputation: 29

Maybe try this:

$this->_helper->viewRenderer->setNoRender();
return;

Upvotes: 2

jackocnr
jackocnr

Reputation: 17416

According to the documentation (under "Pre- and Post-Dispatch Hooks"), calling _forward() in preDispatch() will skip the action.

Specifically about preDispatch(): "its primary purpose is to make decisions about whether or not the requested action should be dispatched. If not, you should then _forward() to another action, or throw an exception."

Upvotes: 0

Tom&#225;š Fejfar
Tom&#225;š Fejfar

Reputation: 11217

I would throw an exception (and then catch it in error controller) - that's what you do when there is non-recoverable error.

Upvotes: 2

Mads Lee Jensen
Mads Lee Jensen

Reputation: 4658

Theres nothing wrong in using $this->_forward() inside the init() (if the method you want to forward to is inside the same controller as the init()), this will simply change the request object's controller / action (overwrite what has been set via the router).

An alternative to this would be to create a Zend_Controller_Plugin as it looks like you are handling unexpected errors. Have a look at the Zend_Controller_Plugin_ErrorHandler implementation. So instead of forwarding to another action you would throw an exception, and have your custom plugin check in postDispatch() if the response contains eny expections, and if it does simply edit the current Request object to show your "cancel" action.

$request->setDispatched(false)
        ->setControllerName("error")
        ->setActionName("jsonDecoding");

The last way could be to just throw a exit after the echo "{error: "invalid json"}" not very nice but you will avoid the overload of having another dispatch iteration.

Upvotes: 2

Related Questions