Custom Flash Messenger for Zend Framework

FlashMessenger
is an action helper in Zend Framework used to pass messages for the users on the next request.

Thats all good, but what about presenting the messages for the users? how to store different type of messages, System, Error, or Success messages?


To achive my goal, i have built two classes, one is an action helper and the other one is view helper.

Action Helper Class

This action helper class act as a factory and singleton pattern. It store the messages in different namespaces of the flash messenger. You can also, retrieve a namesapce by its key to add another message.

<?php
/**
 *
 * @copyright  2009 Mohammed Alsharaf
 * @author     Mohamed Alsharaf (mohamed.alsharaf@gmail.com)
 * @category   Moo
 * @package    Moo_Controller
 * @copyright  Copyright (c) 2009-2010 Mohammed Alsharaf.
 * @version    Release: 0.0.2
 * @link       http://jamandcheese-on-phptoast.com/
 */
class Moo_Controller_Action_Helper_Messenger extends Zend_Controller_Action_Helper_Abstract
{
    protected $_flashMessenger = null;

    public function messenger($name='error', $message=null)
    {
        if ($name == 'error' && $message === null) {
            return $this;
        }
        if (!isset($this->_flashMessenger[$name])) {
            $this->_flashMessenger[$name] = $this->getActionController()
                                                 ->getHelper('FlashMessenger')
                                                 ->setNamespace($name.'_message');
        }
        if ($message !== null) {
            $message = $this->getActionController()->view->translate($message);
            $this->_flashMessenger[$name]->addMessage($message);
        }
        return $this->_flashMessenger[$name];
    }

    public function direct($name='error', $message=null)
    {
        return $this->messenger($name,$message);
    }
}

View Helper Class

The view helper loops all the namespaces of the flash messenger and render the messages using the htmlList view helper

/**
 *
 * @copyright  2009 Mohammed Alsharaf
 * @author     Mohamed Alsharaf (mohamed.alsharaf@gmail.com)
 * @category   Moo
 * @package    Moo_View
 * @copyright  Copyright (c) 2009-2010 Mohammed Alsharaf.
 * @version    Release: 0.0.2
 * @link       http://jamandcheese-on-phptoast.com/
 */
class Moo_View_Helper_Messenger extends Zend_View_Helper_Abstract
{
    const DEFAULT_MSG = 'info';

    protected $_messageKeys = array(
        'msg_message',
        'error_message',
        'info_message',
        'success_message',
        'warning_message',
    );

    protected $_flashMessenger = null;

    public function messenger($messages = null)
    {
        if ($messages !== null) {
            return $this->_renderInjectedMessages($messages);
        }
        $this->_flashMessenger = Zend_Controller_Action_HelperBroker::getStaticHelper('FlashMessenger');

        foreach ($this->_messageKeys as $messageKey) {
            $messages = $this->_getMessages($messageKey);
            if ($messages) {
                echo $this->_renderMessage($messages,$messageKey);
            }
            unset($messages);
        }
    }

    protected function _renderInjectedMessages($messages)
    {
        if (!is_array($messages)) {
            return $this->_renderMessage((string) $messages,self::DEFAULT_MSG);
        }

        $return = '';
        foreach ($messages as $messageKey => $message) {
            $return  .= $this->_renderMessage($message, $messageKey . '_message');
        }
        return $return;
    }
    protected function _getMessages($messageKey)
    {
        $result = array();
        $this->_flashMessenger->setNamespace($messageKey);

        if ($this->_flashMessenger->hasMessages()) {
            $result = $this->_flashMessenger->getMessages();
        }

        // check view object
        if (isset($this->view->$messageKey)) {
            array_push($result, $this->view->$messageKey);
        }

        //add any messages from this request
        if ($this->_flashMessenger->hasCurrentMessages()) {
            $result = array_merge( $result, $this->_flashMessenger->getCurrentMessages());
            //we don?t need to display them twice.
            $this->_flashMessenger->clearCurrentMessages();
        }
        return $result;
    }

    protected function _renderMessage($message, $name)
    {
        if (!is_array($message)) {
            $message = array($message);
        }
        return $this->view->htmlList($message, false, array('class'=>$name), false);
    }
}

Usage:

In your controller to add a message for the next request

// option one
$this->_helper->messenger('success',"Your message is here.");
// another option to add message
$this->_helper->messenger('success')->addMessage('Your message is here.');

To add a message in the current view:

$this->view->info_message = 'stiky message for the current view';

In your layout file add the following, so if there are messages to view, the helper will print them.

<div id="messages">&lt;?php $this->messenger(); ?></div>
Posted in PHP, Zend Framework and tagged , , , .
Loading Facebook Comments ...

Leave a Reply

Your email address will not be published. Required fields are marked *

6 Comments

  1. Hey Mohammed,

    Thanks for your script, it’s been really handy. All I had to do was just create a view_help to render the output as I wanted.

    Cheers.

  2. Pingback: Zend Framework Blog » Blog Archive » Aus den Zend Framework Blogs

  3. Hi Mohammed!
    Thanks for your answer. I solved the problem by adding these lines to the _getMessages method:

    //add any messages from this request
    if ($flashMessenger->hasCurrentMessages()) {
    $result = array_merge(
    $result,
    $flashMessenger->getCurrentMessages()
    );
    //we don’t need to display them twice.
    $flashMessenger->clearCurrentMessages();
    }

    Now the result of this form validation is shown without forwarding/redirection.

    if ($this->_request->isPost() && $form->isValid($_POST)) {
    $this->_contactRow->setFromArray($form->getValues());
    $this->_contactRow->save();
    $this->_helper->messenger(‘success’,”Your message is here.”);
    } elseif ($this->_request->isPost() && !$form->isValid($_POST)) {
    $this->_helper->messenger(‘error’,”Your message is not here.”);
    }

  4. Hi Philipp

    if you would like to use forwarder instead of redirector, do this

    class IndexController extends Zend_Controller_Action
    {
        public function indexAction()
        {
        	$this->view->info_message = 'Your message';
            $this->_forward('next', 'index', 'default');
        }
        
        public function nextAction()
        {
        	
        }
    }
    
  5. Hi mohammed!
    Thanks for this nice implementation of the Zend FlashMessenger. But I realized, that I always need a redirection to fire the message. Using the base addMessage() method, there is no need of a redirection. Any ideas?

    Greetings from munich! Philipp