A consistent message and notification implementation is one of the key building stones of modern web apps. ZF2 makes it very easy to implement this with the FlashMessenger controller plugin.
To integrate the flash messenger into your web app you need to follow 3 simple steps.
First, register the FlashMessengers messages as a view variable in your Module.php. The FlashMessenger supports namespaces which is very useful for having different styling for different message contexts. This example uses 3 different namespaces. You are free to implement as many as you want. I’m merging the default namespace with the info namespace which lets you assign general messages without the need to specify a namespace.
public function onBootstrap(MvcEvent $e) { $eventManager = $e->getApplication()->getEventManager(); $moduleRouteListener = new ModuleRouteListener(); $moduleRouteListener->attach($eventManager); // Show flashmessages in the view $eventManager->attach(MvcEvent::EVENT_RENDER, function($e) { $flashMessenger = new FlashMessenger; $messages = array(); $flashMessenger->setNamespace('success'); if ($flashMessenger->hasMessages()) { $messages['success'] = $flashMessenger->getMessages(); } $flashMessenger->clearMessages(); $flashMessenger->setNamespace('info'); if ($flashMessenger->hasMessages()) { $messages['info'] = $flashMessenger->getMessages(); } $flashMessenger->clearMessages(); $flashMessenger->setNamespace('default'); if ($flashMessenger->hasMessages()) { if (isset($messages['info'])) { $messages['info'] = array_merge($messages['info'], $flashMessenger->getMessages()); } else { $messages['info'] = $flashMessenger->getMessages(); } } $flashMessenger->clearMessages(); $flashMessenger->setNamespace('error'); if ($flashMessenger->hasMessages()) { $messages['error'] = $flashMessenger->getMessages(); } $flashMessenger->clearMessages(); $e->getViewModel()->setVariable('flashMessages', $messages); }); }
To have the messages display consistently throughout your application it is best to add the message HTML to the layout template (in most cases module/Application/view/layout/layout.phtml).
<?php if ($this->flashMessages) { foreach ($this->flashMessages as $context => $messages) { echo '<div class="message-container ' . $context . '"><ul>'; foreach ($messages as $message) { echo '<li>' . $message . '</li>'; } echo '</ul></div>'; } } ?>
Finally you can assign messages in your controller. You don’t need to specify a namespace if you want to assign messages to the info group.
$flashMessenger = $this->flashMessenger(); $flashMessenger->setNamespace('success'); $flashMessenger->addMessage('Foo!');
Hi Michael,
Just thought I’d leave you a comment as I hit a problem whilst I was trying to do exactly this. Whilst it works in simple cases, where only a single point in an application is trying to access flash messages, things get messy when multiple modules do this.
The FlashMessenger (by virtue of its “getMessagesFromContainer” function, which is called by both “hasMessages” and “getMessages”) will pull all messages from the session into the current instance of the FlashMessenger.
By instantiating a new FlashMessenger object instead of using the one in the Service Manager, you will prevent anything else from accessing messages, across all namespaces.
Conversely, if something else in your application gets to call “getMessages” or “hasMessages”, either on the FlashMessenger instance from the ServiceManager, or from their own freshly instantiated FlashMessenger, you will find that your instance contains no messages as they have already been “stolen” by the earlier instance.
Using “$e->getApplication()->getServiceManager()->get(‘ControllerPluginManager’)->get(‘flashMessenger’);” instead avoids this.
As long as everyone else behaves and does the same, of course 😉