Zend Framework's Flash Messenger action helper
I’ve talked about Zend Framework’s action helpers before, but haven’t covered any of the action helpers that are supplied with Zend Framework.
FlashMessenger is a helper that allows you to store messages between requests. The most common use I have for it is for a “saved” message after doing an edit of an item that then redirects back to a list.
This is how it’s used:
Storing a message
Storing to the FlashMessenger is easy. This is my typical usage within an action controller:
$this->_helper->flashMessenger->addMessage('Task saved');
$this->_helper->redirector('index');
This code adds the message “Task saved” to the FlashMessenger and then redirects the user the index action, which in this case is a list of tasks. As should be obvious from the name of the method, you can add multiple messages and they will all be stored for retrieval after the next redirect.
The FlashMessenger will store the message that you’ve added for one hop, or number of requests. This means that the message will be available for retrieval on the next request, but unavailable on the request afterwards. This is very useful and it means that if someone refreshes the task list by hitting F5, then the “Task saved” message does not reappear.
Retrieving the stored messages
Retrieving the stored messages is similarly simple:
$this->view->messages = $this->_helper->flashMessenger->getMessages();
This will create an array of messages in your view object which you can then loop over in your view script:
<?php if (count($this->messages)) : ?>
<ul id="messages">
<?php foreach ($this->messages as $message) : ?>
<li><?php echo $this->escape($message); ?></li>
<?php endforeach; ?>
</ul>
< ?php endif; ?>
and that’s all there is to the FlashMessenger.
I catch the messages from the flashMessenger in a view helper. This means I only need to create messages in my controllers, the view is able to retreive them itself.
By default my layout scripts loads the messages so it's really simple to display flashMessenges, even action view scripts don't need to care about them.
if You want to display messages without redirect (for example custom error) You have to do somethink like that:
$this->view->messages = array_merge(
$this->_helper->flashMessenger->getMessages(),
$this->_helper->flashMessenger->getCurrentMessages()
);
$this->_helper->flashMessenger->clearCurrentMessages();
This works even if no redirect has been made.
hi rob
It is possible ? :
$this->_helper->flashMessenger->addMessage('Task saved');
$this->_forward('index');
zaman,
Yes, but you need to use getCurrentMessages() to retrieve the message that you have added.
Regards,
Rob…
I know this probably isn't the best way to do it, but I wrote this before the flash message helper was in place. In my instance I like to tell it what type of message I'm passing it, a confirmation or an error. I style the message differently depending on the type.
Here is where I call the helper:
$this->displayError($this->message, $this->message_class, $_SESSION['message'], $_SESSION['message_class']);
As you can see I pass it a local variable and a session value. If I create the message when I'm going to redirect them I use session, if it's created in the controller just before the action is called I use a local variable within the view object.
<?php
Zend_Loader::loadClass("Zend_View_Helper_Abstract");
class Fp_View_Helper_DisplayError extends Zend_View_Helper_Abstract
{
public function displayError($message, $message_class, $flash_message, $flash_class)
{
$display_message;
$display_class;
$display = "none";
if($message != "")
{
$display_message = $message;
$display_class = " class="".$message_class.""";
$display = "block";
}
if($flash_message != "")
{
$display_message = $flash_message;
$display_class = " class="".$flash_class.""";
$display = "block";
unset($_SESSION["message"]);
}
return "
Close
".$display_message."
";
}
}
@zaman: that's why I use a view helper. The helper retreives both the "old" messages and appends the messages created in the current request.
You can also distinguish between them by setting the options to get only the current messages or just the messages from previous requests.
@Luke: I'd suggest looking at the flashMessenger again. Nobody says you can only add strings as messages ;) Most of the time, I add such a message:
$this->flashMessenger(array('success' => 'You are now logged in!'));
This key/value pair contains the message type and message text. The view helper renders the classes together with the message text.
@Jurian I hadn't thought of that, that's a much cleaner solution.
One issue I have run into is losing flash messages if a double redirect happens. Has anyone figure out how to stop flash messages from being deleted before they are shown?
You have to get flashMessenger session namespace and change expiration hops.
But IMHO it is wrong if double redirect is made.
Hi Rob,
I wrapped FlashMessenger as an Action Helper, because I wanted to pass message type and text. Anyway, but, I have no idea how I can write a unit test for my Action Helper without controller. Have any idea?
$flashMessenger->setNameSpace('actionErrors') in ZFIA pg 135
Is this an error or deprecated?