Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 804
Steve Clay Avatar asked Oct 19 '10 17:10

Steve Clay


4 Answers

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.

like image 155
Mads Lee Jensen Avatar answered Oct 23 '22 07:10

Mads Lee Jensen


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

like image 38
Tomáš Fejfar Avatar answered Oct 23 '22 06:10

Tomáš Fejfar


Maybe try this:

$this->_helper->viewRenderer->setNoRender();
return;
like image 21
mouadkrt Avatar answered Oct 23 '22 07:10

mouadkrt


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.

like image 31
FDIM Avatar answered Oct 23 '22 07:10

FDIM