views:

2027

answers:

5

How could I send additional view parameters after I have done a redirect (e.g. $this->_redirect->gotoSimple();)?

For example, let's say I have an Edit action which will redirect the user to an Error action handler and I would like to be able to send custom, detailed error messages to its view. To illustrate it clearer, the flow would be:

  1. At the Edit view (say, http://localhost/product/edit), the user submits something nasty
  2. At editAction(), a fail check triggers a redirect to my Error view/action handler (so that my URL would read like http://localhost/error/index)
  3. The Error/index.phtml takes a "errorMessage" view variable to display the custom error message, and editAction() needs a means to pass in some value to that "errorMessage" view variable

A quick code snippet would probably look like:

public function editAction() {
    //DO THINGS...

    // Upon failure
    if($fail) {
        $this->_redirector->gotoUrl('/error/index');
        //TODO: I need to be able to do something like
        //      $errorView->errorMessage = "Generic error";
    }
}

Any solutions, or even other better ways of achieving this, is greatly appreciated.

+4  A: 

Don't use gotoURL() for internal redirects. Use gotoSimple(). I takes up to 4 parameters:

gotoSimple($action, 
           $controller = null, 
           $module = null, 
           array $params = array())

In your case it's going to be:

$this->_redirector->gotoSimple('index',
                               'error',
                                null,
                                array('errorMessage'=>$errMsg));

See Redirector Zend_Controller_Action_Helper for details.

vartec
+2  A: 

I have not seen anywhere that an action (editAction) accesses another action's view (errorView). for the special case of error handling, my idea is using Exceptions. you throw different exceptions for different bad situations, and in your error handler action, you can decide what to show to user based on the exception type:

// file: ProductContorller.php
public function editAction() {
    // some code
    if ($badThing) {
         throw new Exception('describe the bad thing',$errorCode);
    }
    if ($badThing2) {
         throw new Exception('describe the other bad thing',$errorCode2);
    }
}

// file: ErrorController.php
public function errorAction() {
     $error = $this->_getParam('error_handler');
     $exception = $error->exception; // the original Exception object thrown by some code
     $code = $exception->getCode();
     switch ($code ) {
          // decide different things for different errors
     }
}

for more information about error handling, the Zend Framework quick start is a great tutorial.

for other situations, you can use some messaging mechanism to communicate between these 2 actions. using flashMessenger action helper is the first thing comes into my mind:

// file: ProductContorller.php
public function editAction() {
    // some code
    if ($badThing) {
         $this->_helper->flashMessenger->addMessage('error1');
         $this->_redirect('error');
    }
    if ($badThing2) {
         $this->_helper->flashMessenger->addMessage('error2');
         $this->_redirect('error');
    }
}

// file: ErrorController.php
public function errorAction() {
     $errors = $this->_helper->flashmessenger->getMessages();
     if ( in_array('error1',$errors) ) {
       // do something
     } // elseif ( ...
}

although remember that flashMessenger uses sessions, so sessions and most likely cookies are going to be involved in this messaging process.

farzad
+3  A: 

The standard way of doing this is with a session-based store of a message you wish to display. It's common enough that there is a view-based helper, FlashMessenger.

The FlashMessenger helper allows you to pass messages that the user may need to see on the next request. To accomplish this, FlashMessenger uses Zend_Session_Namespace to store messages for future or next request retrieval. It is generally a good idea that if you plan on using Zend_Session or Zend_Session_Namespace, that you initialize with Zend_Session::start() in your bootstrap file. (See the Zend_Session documentation for more details on its usage.)

Alister Bulman
This is really the best way to pass messages in general. The accepted answer is a more specific case for exceptional errors.
David Caunt
A: 

go through this link.. it explains how can we set view variables before _redirect

http://www.rmauger.co.uk/2009/06/creating-simple-extendible-crud-using-zend-framework/

Anusha
A: 

I'll add this to give some more info on how the FlashMessenger class works ( I had some issues figuring it out).

I read somewhere that a session should be started in Bootstrap.php using

Zend_Session::start();

..but my code worked without that, so I suspect sessions are already started.

We're in a controller-object and an action-method is being called. Then something happens, like an insert or an edit into the database, anything really.

We now set one or more messages. I use the following syntax.

$this->_helper->FlashMessenger("Message in a bottle.");

Which is exactly the same as using

$this->_helper->FlashMessenger->addMessage("Message in a bottle.");

This sets a message in the session, you can check that directly by calling

print_r($this->_helper->FlashMessenger->getMessages());
die();

Now there's a redirect to a new url (so a new request basically), inside the controller+action that is handling the request we'll add the messages to the view like so:

$this->view->flashMessages = $this->_helper->FlashMessenger->getMessages();

We now have a choice of where to output these messages. We can do this inside a view that "belongs to" a certain controller, so that could be

views/scripts/index/index.phtml

The drawback here is that you'd have to add the code outputting the messages to every viewscript that uses it. That's not very DRY.

In my eyes a superior solution is the following. Output these messages at in the file where you define the basic layout of your application. That's probably

layouts/scripts/index.phtml

I wrote the following code there.

<?php if( isset($this->flashMessages) && !empty($this->flashMessages) ){ ?>
    <ul id="messages">            
        <?php foreach( $this->flashMessages as $message ){?>
            <li>
                <?php echo $message;?>
            </li>    
        <?php } ?>
    </ul>
<?php } ?>
Niels Bom