RSS
 
21. Apr. 2014

CakePHP flash messages 2.0

21 Apr

This is a topic often discussed. What is the best approach? While I might not have the best, I sure have a fully working one since 2008 and CakePHP1.3. I still use it in all 2.x apps. It is easy and does not require a lot of overhead.

Basically, it enhances the core one with the following features

  • Different types possible (now in 2.x kind of in the core, as well, using elements)
  • Multiple flash messages per type possible (with a max limit to avoid session flushing)
  • Transient messages (via Configure) and real ones (via Session)
  • Transient ones can also be fired from the views (to display some hint/info for this page) – although one should try to stick to the controller

Demo

sandbox/examples/messages

How does it work?

We attach the Common Component and the Common Helper to the AppController:

public $components = array(..., 'Tools.Common');
public $helpers = array(..., 'Tools.Common');

In our layouts we need to switch the default output to ours:

echo $this->Common->flash();

And we can use `em:

public function add() {
    ...
    if ($this->Entry->save()) {
        $this->Common->flashMessage('The Entry has been saved.', 'success');
    } else {
        $this->Common->flashMessage('The Entry could not be saved. Please check the form.', 'error');
    }
}

Styling

We style our flashmessages via CSS

div.flash-messages {
    width: 90%;
}
div.flash-messages div {
    padding: 10px;
    padding-left:40px;
}
div.flash-messages div.error {
    width:100%; border-style: solid; border-width:1px; border-color:#B84D17; 
    margin-right:2px; color:#000000; margin-bottom:8px;
    background: url(/img/css/layout/icon_error.gif) left center no-repeat;
    background-color:#F7C6A5;
}
div.flash-messages div.warning {
    width:100%; border-style: solid; border-width:1px; border-color:#D0C130; 
    margin-right:2px; color:#000000; margin-bottom:8px;
    background: url(/img/css/layout/icon_warning.gif) left center no-repeat;
    background-color:#F6F3A4;
}
div.flash-messages div.success {
    width:100%; border-style: solid; border-width:1px; border-color:#009900; 
    margin-right:2px; color:#000000; margin-bottom:8px;
    background: url(/img/css/layout/icon_success.gif) left center no-repeat;
    background-color:#A5F7A8;
}
div.flash-messages div.info {
    width:100%; border-style: solid; border-width:1px; border-color:#cccccc; 
    margin-right:2px; color:#000000; margin-bottom:8px;
    background: url(/img/css/layout/icon_info.gif) left center no-repeat;
    background-color:#ffffff;
}

Or any other layout for that matter. The images are small icons and also optional, of course :)

Transient flash messages

You can also put flash messages on top that are not stored in session but Configure (for this request only). This can be useful if you don’t intend to redirect and don’t want them to show up if that happens.

From your controller:

$this->Common->transientFlashMessage('This page is currently being redesigned', 'info');

Or from your view ctp (even elements, blocks or the layout if it happens prior to the flash message output):

$this->Common->addFlashMessage('This page is under maintenance. It may be broken!', 'warning');

Output in a specific order or only specific types

You can filter the output, both in order and types:

// Using Common helper
echo $this->Common->flash(array('warning', 'error'));

In this case it would only output the warning and error messages, in this order (Usually the order is “error, warning, success, info”).

Details

For details please the Wiki page.

Outview

It would probably be nice to add element support at some point. This would allow an easier approach to customization of those messages.

There are also quite a few CakePHP core tickets open regarding flash message enhancements – see this or this which might even lead to an own component for it some day. But until then my approach will still be used in all my xx apps :) So in 3.x there will be a Flash component and Flash helper to provide a clean way to produce flash messages. If they provide the same features my implementation currently does, will have to be investigated. But it will use templating which will sure be nice.

CakePHP flash messages 2.0
0 votes, 0.00 avg. rating (0% score)
 
3 Comments

Posted by Mark in CakePHP

 

Tags: , ,

Leave a Reply

Tip:
If you need to post a piece of code use {code type=php}...{/code}.
Allowed types are "php", "mysql", "html", "js", "css".

Please do not escape your post (leave all ", <, > and & as they are!). If you have encoded characters and need to reverse ("decode") it, you can do that here!
 

 
  1. Ankan Ad

    April 21, 2014 at 12:04

    Hi Mark!

    Always a fan. My question, in the same context is – What is the best way to set flash messages from the model? Most of my logic are in model methods, and I would like to make the respective method responsible for handling/returning the flash message, along with a true/false to the controller.

    (1) setting a variable like

    $this->errorMsg

    in the model and then doing

    setFlash($this->model->errorMsg)

    in the controller works – but it is not neat, especially when many models are involved.

    (2) Writing to the session from the model also doesn't seem sweet because, what if the model is used in a shell with no session?

    What would be a good general approach?

     
  2. Mark

    April 21, 2014 at 12:11

    For errors you can probably throw an exception FlashException and catch that in the controller layer. Even though that would make a lot of overhead and is therefore not the most tempting approach.

    The session is usually always available in some way – in CLI cake emulates it AFAIK in a way that it is still useable if you want it to. That would sure be the quickest "hack" solution from all.
    "Hack" because then you would probably want to rewrite the flash message system from the component into the model layer to keep it DRY.

    I guess it depends on the use case.
    For most I would probably use my "Transient Flash Message" approach. That is probably the best way as it writes to Configure which is then added to the output of flash messages in the view.

    If you want to persist them across redirects, you would need to add them to the session prior to redirecting in the beforeRedirect() callback of the controller or a component callback.

     
  3. Ankan Ad

    April 30, 2014 at 02:04

    Hi Mark!

    This maybe a noob question. How about completely decoupling flash messages into a neat framework like toastr.js?

    Working demo:
    http://codeseven.github.io/toastr/demo.html