January 13, 2008 11

Session-Based Flash Messages Look Better (CakePHP)

CakePHP

The CakePHP blog tutorial uses a rather archaic method of displaying user messages (like, “Your post has been saved.“) that needlessly breaks up the flow of your application. Rather than Cake’s typical method of displaying flash messages on a separate page (ugly), learn how to seamlessly display the same messages within your application and make your users clap with joy.

See What I Mean?

Let me show you exactly what I’m talking about using some screen shots I took of my own application.

These first two screen shots show the index page and post page of my news application:

(At the moment, nothing is posted on the index page.)
CakePHP Session-Based Messages - Part 1

(A typical form allows the user to post a new news article…)
CakePHP Session-Based Messages - Part 2

When we post a new news article, the typical Cake method is to display a flash message on a separate page, forcing the user to temporally leave your application. This method is distracting for the user and makes your application feel broken up. (To return to the news index page, the user is forced to click the “Your post has been saved” message.)

CakePHP Session-Based Messages - Part 3

Instead of the above method, let’s use the same messages in a Web 2.0 fashion. After a news article is posted, we can automatically redirect the user back to the index page AND display the message on the same page:

CakePHP Session-Based Messages - Part 4

See what I mean? Allow me to show you how it’s done…

Configure Your Layout

In order to display the awesome-web-2.0-styled messages, we need to add a line of code to your app/views/layouts/default.thtml page, above the code which displays your layout content:

check('Message.flash')): $session->flash(); endif; // this line displays our flash messages
   echo $content_for_layout;
?>

Configure Your Controller

Next comes the line you must add to your app/controllers/news_controller.php controller to display your message and redirect your user to a particular page:

function add() {
// ...
   if ($this->News->save($this->data)) {
      $this->Session->setFlash('Your post has been saved.');
      $this->redirect('/news/index');
     //$this->flash('The News has been saved', '/news/index'); // this was the old way of doing things... yuck
   }
}

All Done!

Now when a flash message is displayed, it’ll be placed in a div (directly above the layout content) for easy style manipulation:

Your post has been saved.

Easy as cake. If you have any questions or suggestions, please post.

Tags:

11 Responses to “Session-Based Flash Messages Look Better (CakePHP)”

  1. [...] Session-Based Flash Messages Look Better (CakePHP) – Labs Flashier flash messages in CakePHP (tags: cakephp session flash) [...]

  2. leveille says:

    I agree with your assessment that the use of the intermediate flash page intrudes into the normal application flow. I implement a technique whereby I create a flash element, and render this flash element at the top of my template.

    
    element('flash');
    
    

    The flash element consists of code to check whether or not the message being sent is an error, warning, or success:

    
       check('Message.err'))
          {
             echo '';
             $session->flash('err');
             echo '';
          }
    
       check('Message.warn'))
          {
             echo '';
             $session->flash('warn');
             echo '';
          }
    
       check('Message.succ'))
          {
             echo '';
             $session->flash('succ');
             echo '';
          }
    
    

    I also make use of these div’s for javascript feedback, which is why I don’t programmatically display the actual div/class. They’re always ready to be injected with user feedback. The p tags on the other hand are displayed when appropriate, as those are what get styled via css.

    In my controller I set the type of flash message and redirect to the appropriate location:

    
    $this->Session->setFlash('The lesson you have selected is unavailable or invalid.  Please try again.', null, null, 'err');
    $this->redirect(array('action'=>'index'));
    
    

    Just thought I would share. This technique may or may not be helpful to others.

  3. Djiize says:

    @leveille: or you can use the 2nd param of setFlash to specify a layout $this->Session->setFlash(‘bad values’, ‘flash_err’)
    then create your layouts: flash_err.ctp, flash_warn.ctp, flash_succ.ctp
    and just call $session->flash() in you default layout
    Leave boring work to Cake, it exists for that ;)

  4. Jonah says:

    Thanks for the article and the comment from Djiize. I now know how to use the Session->setFlash() funtion!

  5. connector says:

    Thanks for the nice tutorial. One question, can you tell my what wysiwy editor you used in the screenshots? Thanks!

  6. Koa says:

    connector, I’m using TinyMCE as the WYSIWYG editor. Enjoy!

  7. deltawing1 says:

    Thanks for this tutorial!

    Oh and thank you Djize! I’ve been needing exactly that technique :-)
    The elegant and “correct” way to do it.

  8. mark says:

    I did find your posting very useful, although i created my own helper class “Flash” for this one.
    This was needed, because CakePHP is not able to put more then 1 Message of each category (error, success etc) in the SESSION.

    So if your app throws a second error somewhere, the first one will be deleted silently, which is really a problem at some points!

    I put them in an array, and therefore can store multiple ones, which are (by the helper) read out and displayed.

    Next thing i wanna build in, is a sorted display. Not random, but in the order of importance: Error -> Warning -> Success -> Info

  9. headbiznatch says:

    useful tidbit here – thank you.

    i played around with Impromptu, a nifty jQuery extension, and got a nice modal message box that i put in my default.ctp attached to the body onload. funky. here’s the link to impromptu:

    http://trentrichardson.com/Impromptu/index.php

    and here is the snippet i put in my template before the closing “>” of the body tag:

    check(‘Message.flash’)): echo ‘onload=”$.prompt(\”; $session->flash(); echo ‘\’);”‘; endif; ?>

    rock.

  10. headbiznatch says:
    
    check('Message.flash')): echo 'onload="$.prompt(\''; $session->flash(); echo '\');"'; endif; ?>;