aufziehvogel
aufziehvogel

Reputation: 7297

How can I replace this _forward() with something that can exit?

I use the following code over and over in my zend framework application. It is used in action() to check if an article exists. If not, the user shall see an error message:

$article = ArticleQuery::create()->findOneByUrl($this->_getParam('url', ''));

if (!$article) {
    $this->getResponse()
         ->setRawHeader('HTTP/1.1 404 Not Found');
    return $this->_forward('error', null, null, array(
        'message' => 'Article not found',
    ));
}

I was wondering how to factor this out into an own method to reduce the code load in all actions.

I came to something like this:

protected function myAction() {
    $article = $this->getArticleIfExists($this->_getParam('url', ''));
    if ($article == null) {
        return;
    }
}

protected function getArticleIfExists($url) {
    $article = ArticleQuery::create()->findOneByUrl($this->_getParam('url', ''));

    if ($article) {
        return $article;
    } else {
        $this->getResponse()
             ->setRawHeader('HTTP/1.1 404 Not Found');
        $this->_forward('error', null, null, array(
            'message' => 'Article not found',
        ));
        return nulL;
    }
}

I still would like to get rid of the if case in myAction(), but _forward() does not allow to exit the execution (of course, because it still needs to execute the other actions).

Another possibility (I have implemented in some other controllers) is this:

protected function myAction() {
    $article = ArticleQuery::create()->findOneByUrl($this->_getParam('url', ''));

    if (!$article) {
        return $this->notFound('Article does not exist');
    }
}

protected function notFound($message) {
    $this->getResponse()
         ->setRawHeader('HTTP/1.1 404 Not Found');
    return $this->_forward('error', null, null, array(
        'message' => $message,
    ));
}

Again we have this if check in the action. It’s already better than before, but can we make it even better?

How can I circumvent this? Is there a possibility to do it without losing the current URL? With a Redirector I can of course exit, but then I would lose the current URL (/controller/myaction/url/hello -> /error/error/message/Article%20not%20found)

Upvotes: 0

Views: 130

Answers (2)

RockyFord
RockyFord

Reputation: 8519

For something as simple as just displaying a "* does not exist" against a user request I prefer to leave the user in the application and just hit them with a flashmessenger notice and leave them on the page to make another request (if appropriate):

public function indexAction() {

        //get form and pass to view
        $form = new Form();

        $this->view->form = $form;

        try {
            //get form values from request object
            if ($this->getRequest()->isPost()) {
                if ($form->isValid($this->getRequest()->getPost())) {

                    $data = $form->getValues();

                   // Do some stuff
                }
            }
        } catch (Zend_Exception $e) {

            $this->_helper->flashMessenger->addMessage($e->getMessage());//add message to flashmessenger
            $this->_redirect($this->getRequest()->getRequestUri());//perform redirect to originating page so the messenger will flash
        }
    }

This is simple and works well when the possibility for incorrect user input exists.

Upvotes: 1

Moe
Moe

Reputation: 2730

A possible approach would be to throw an Exception. Because of the Zend_Controller_Plugin_ErrorHandler this will automatically redirect you to the ErrorController without any further code being executed.

If you don't want to get to the ErrorController but only to the current controller's error actions, you can simply modify the plugin in the controller's init method:

public function init()
{
    $plugin = Zend_Controller_Front::getInstance()->getPlugin('Zend_Controller_Plugin_ErrorHandler');
    $plugin->setErrorHandlerModule('default')
       ->setErrorHandlerController('MyController')
       ->setErrorHandlerAction('error');
}

But of course you can also write your own ErrorHandler plugin for a more fine grained error handling. This is described in the Zend Framework Manual on Plugins

Upvotes: 1

Related Questions