Custom CakePHP Flash Messages Updated

22nd May 2009 CakePHP
CakePHP Flash Messages

I've been quite inactive recently and had a few comments about the "flash messages" article and it's really outdated so I thought I would do a quick update. Last time I created a new class that extended the SessionHelper but that isn't necessary and the process is much simpler. I'm using CakePHP 1.2.3.8166 in this article.

Layouts

I'm going to create two new layouts that will be used for either a "good" or a "bad" flash message. Then when I'm setting the flash message in the Controller I'm going to specify which layout to use.

// file: /app/views/layout/flash_bad.ctp
<div class="flash_bad">
	<a href="/" class="cancel"><img src="/img/icons/cross.png" alt="Cross Icon" /></a>
	<?php echo $content_for_layout; ?>
</div>
// file: /app/views/layout/flash_good.ctp
<div class="flash_good">
	<a href="/" class="cancel"><img src="/img/icons/cross.png" alt="Cross Icon" /></a>
	<?php echo $content_for_layout; ?>
</div>

Set Flash

Now when setting a flash message we can simply specify which layout to use.

// controller code
$this->Session->setFlash('You have successfully logged in','flash_good');
$this->Session->setFlash('Error: invalid username and/or password','flash_bad');

CSS

Here are some sample styles that you can use for the flash messages, nothing fancy but they get the job done.

// css styles
.flash_good { 
background: #e5f2be; 
border:2px solid #bedf5d; 
padding:10px; 
font-weight:bold;
}
.flash_bad { 
background: #eccecf;
border:2px solid #9e0b0f;
padding:10px;
font-weight:bold;
}
.flash_good img, .flash_bad img {
float:right;
}

Additional jQuery enhancements

Chris suggested adding some nice jQuery functionality to have the messages fade out on a click and I've also added some extra code to fade out messages after a delay. Include the jQuery library in your application along with the below code to add some extra flair to your flash messages.

// file: /app/webroot/js/common.js
$(document).ready(function(){
	// fadeout flash messages on click
	$('.cancel').click(function(){
		$(this).parent().fadeOut();
	return false;
	});

	// fade out good flash messages after 3 seconds
	$('.flash_good').animate({opacity: 1.0}, 3000).fadeOut();
});

The first bit of code will fade out the flash message when a user clicks on the cancel link and the second will fade out the message after 3 seconds. Here I've only faded out the good messages because if something went wrong I'd want to keep the message for the user.

Wrapping Up

Well as you can see this is much easier than my last article on setting flash messages and this will hopefully help some of you out. Any questions etc then leave a comment.

UPDATE: Chris kindly suggested that I include some Javascript to fade out the messages so that's now been included.

Back to Home Page

Comments

Chris (22/05/2009 - 00:52)

Hello from another northwest baker! Great stuff as always James - nice to see this has been simplified - it was a bit convoluted before! I'll be using this is my current app.

How about extending this to use jQuery (or other) to add a dismiss button or make the message fade out after a defined time period?

James (22/05/2009 - 04:47)

@Chris: Very good idea, I'll get it done over the weekend using jQuery. It won't be too difficult to accomplish.

Kevin (22/05/2009 - 07:02)

@Chris you took the words right out of my mouth.

StevenAFC (24/05/2009 - 03:30)

This is much cleaner method than before!

I have a question though, how can you apply a layout style to messages put out by cake itself, such as:

$this->Auth->authError = "Please login to perform that action.";

James (24/05/2009 - 05:26)

@StevenAFC: I've had a quick look at the Auth component code and it looks like the "default" layout is hard coded when the flash message is set so it doesn't look like its possible to change without overriding any of the core code. Off the top of my head you could extend the SessionHelper and override the "flash()" method. If the $key is set to "auth" then change the layout that the error message uses. It's a bit overkill so I probably wouldn't bother doing it myself.

Neil Crookes (24/05/2009 - 13:41)

app/app_helper.php
<?php
class AppHelper extends Helper {
var $helpers = array('Session');
function sessionFlash() {
if ($this->Session->check('Message.flash')) {
$this->Session->flash();
return;
}
if ($this->Session->check('Message.auth')) {
$_SESSION['Message']['auth']['layout'] = 'flash_bad';
$this->Session->flash('auth');
return;
}
}
}
?>

StevenAFC (24/05/2009 - 23:13)

@James: Yep you are right, I had a look in auth, and I have exposed the layout variable, so I now have pretty cake messages.

I am surprised that it has been hardcoded like that.

James (25/05/2009 - 02:09)

@Neil: Hey thanks for commenting and taking the time to come up with some sample code, much appreciated and I'm sure it will help out StevenAFC and a few others who came across similar problems.

beeman (12/06/2009 - 00:57)

Hi James, nice tutorial.

One comment: the two CTP files should ofcourse be in app/views/layouts instead of app/views/layout :)

But it works like a charm!

Steve (17/06/2009 - 14:22)

this does not work when you use view caching. even if you put the $session->flash(); part inside <cake:nocache> tags. see my post on google groups (
"Problem with $this->Session->setFlash when using caching"):

http://groups.google.com/group/cake-php/browse_thread/thread/d889e0555d04490a#

By the way James, your article doesn't mention the use of $session->flash(); in a view or for example the default layout for a website. I guess you use that call somewhere or do you use something else to output the flash message?

Akif (19/06/2009 - 06:01)

Nice work. I'll use this too. The jQuery extension makes it even better.

Keep up the good work, i'll subscribe to your feed.

Bancer (15/08/2009 - 12:32)

I get the similar effect just by using css and customizing setFash. I do not have additional .ctp files.
Here is my code:
$this->Session->setFlash(
sprintf(__('The "%s" record has been saved', true), $id),
'default',
array('class' => 'flash_good')
);

Robert (29/08/2009 - 10:18)

You can also pass the class name for each message via the setFlash method removing the need to create different layouts, e.g.

$this->Session->setFlash('You have successfully logged in', 'default', array('class' => 'flash_good'));

This will still work nicely with the provided jQuery enhancements... but I guess this also would remove the ability to add any other custom elements to the message (like your cross icon).

sparkybarkalot (07/09/2009 - 09:44)

Really awesome article... thanks so much. One thing to fix in your JQuery code that caused me problems: fadeOut apparently needs to have a timing value, such as "slow", "normal", "fast", or a number of milliseconds. My fadeouts wouldn't occur using your code, but they did once I did something like fadeOut("slow").

Thanks again... great, succinct, and very useful!

James (08/09/2009 - 04:45)

@sparkybarkalot: thanks for commenting. That's very strange I've never had any problems excluding the fade speed. In the docs the default is "normal" so I've never had the need to change it.

Carlitos (09/11/2009 - 13:07)

One comment...

Use the header "jQuery(function($){... " for invocate the functions of jQuery!

Thanks...
Brazilian

Matt Kaufman (12/02/2010 - 12:01)

Hey,

Somehow I seem to have forgotten how to build apps in CakePHP (just kidding, it's just been awhile since my last major one in 2008).

Anyway, you have great CakePHP content --- lots of sites suck for it.

kidchunks (15/02/2010 - 20:14)

For those still struggling with this issue. I simply put a <div> tag within the authError.

Ex

$this->Auth->loginError=__('<div class="flash_bad">Invalid username or password</div>',true);

Don't know what errors this will produce later on, but it seems to work.

James (28/02/2010 - 07:53)

@Mary: You could either hash all the passwords in the database which would make your application much more secure or you could remove the md5() part from the function so that just the plain passwords match. I would personally go with the former.

Kurn La Montagne (12/06/2010 - 02:51)

Thank you so much for this article James. I was able to use this to apply the layout to the messages Cake puts out from auth eg authError or failed login attempts by using:

$this->Auth->flashElement = "flash_bad";
Details can be found towards bottom of page here: http://book.cakephp.org/view/1265/AuthComponent-Variables

edge (18/06/2010 - 14:22)

If you want to have another layout for your Auth error message you can define with the 'flashElement' variable that another element will be used for display.
<?php
$this->Auth->flashElement = "message_error";
?>

JaRo (17/07/2010 - 13:22)

Hi there, thanks for this article but it doent' works for me.

First I got message that I have to move those files to "elements" and then I got another message - "Undefined variable: content_for_layout" - but css works :P

Cheers.

randy (09/08/2010 - 13:16)

Per: http://book.cakephp.org/view/1564/Controller-Components

Change $content_for_layout to $message

Add Your Comment

Full Apps

Request a Feature Application Ajax Store Locator Application FilmDB Application TVDB Application CakeBattles Application CakeCatalog Application

Recently Watched Films

Mr Brooks Rec Pathology Diary of the Dead

TV Shows

The Shield Flight of the Conchords

Hosting

I've been using Dreamhost for my hosting for over 2 years and it's pretty good for what you pay. If you're signing up how about showing me some love and use this link so I get a referal bonus to help pay my server costs.

Site by James Fairhurst 2008-2010, all rights reserved and all that malarky