Add a touch of class to your Auth Flash

Have you ever wondered how to make your Auth messages from the Auth Core component, well more flashy and custom? The answer is fairly simple and straight forward. In this short tutorial, I will explain the traceback that occurs when a flash message is set for Auth.

Working on a project today, I realized that my Auth login error messages weren't being displayed in the custom flash layout I had chosen to use for the project. A bit of digging showed me a secret trail through the rabbit hole, and a simple solution to the problem.

First stop on the trail, was /cake/libs/controllers/components/auth.php to investigate where the flash messages were being set, via

$this->Session->setFlash()

I found 3 locations in the auth file, and each were setting the flash to use the default layout. I was curious at that point to where the default layout for flash was set at. Well as it turns out, there isn't one! rather, it's hard coded into the SessionHelper->flash() method, as seen by line # 22 below.

  1. /**
  2.  * Used to render the message set in Controller::Session::setFlash()
  3.  *
  4.  * In your view: $session->flash('somekey');
  5.  *                  Will default to flash if no param is passed
  6.  *
  7.  * @param string $key The [Message.]key you are rendering in the view.
  8.  * @return string Will echo the value if $key is set, or false if not set.
  9.  * @access public
  10.  */
  11.     function flash($key = 'flash') {
  12.         if ($this->__active === true && $this->__start()) {
  13.             if (parent::check('Message.' . $key)) {
  14.                 $flash = parent::read('Message.' . $key);
  15.  
  16.                 if ($flash['layout'] == 'default') {
  17.                     if (!empty($flash['params']['class'])) {
  18.                         $class = $flash['params']['class'];
  19.                     } else {
  20.                         $class = 'message';
  21.                     }
  22.                     $out = '<div id="' . $key . 'Message" class="' . $class . '">' . $flash['message'] . '</div>';
  23.                 } elseif ($flash['layout'] == '' || $flash['layout'] == null) {
  24.                     $out = $flash['message'];
  25.                 } else {
  26.                     $view =& ClassRegistry::getObject('view');
  27.                     list($tmpVars, $tmpTitle) = array($view->viewVars, $view->pageTitle);
  28.                     list($view->viewVars, $view->pageTitle) = array($flash['params'], '');
  29.                     $out = $view->renderLayout($flash['message'], $flash['layout']);
  30.                     list($view->viewVars, $view->pageTitle) = array($tmpVars, $tmpTitle);
  31.                 }
  32.                 echo($out);
  33.                 parent::del('Message.' . $key);
  34.                 return true;
  35.             }
  36.         }
  37.         return false;
  38.     }
  39.  

Rather than simply changing this, and perhaps making it more rigid, I decided to simply add in 2 public variables to the Auth Component, which I can then set, with the rest of my Auth properties in the AppController. Below is the Diff of my Auth Component, as it is from the CakePHP 1.2.5 core. I personally chose:

/**
 *  Flash Layout to use to allow custom layouts.
 *  Defaults to the layout as used by $session->flash()
 *
 *  @var string
 *  @access public
 */

    var $authFlashLayout = 'default';
/**
 *  Flash Error Params to use. Defaults to array() as used
 *  by the Auth component preiviously
 *
 *  @var array
 *  @access public
 */

    var $authFlashError = array();

I can then set the layout I want, and the params to pass to the custom flash message. Below is the complete diff for the Auth Component.

===================================================================
--- cake/libs/controller/components/auth.php    2009-12-01 19:04:51 UTC (rev 55)
+++ cake/libs/controller/components/auth.php    2009-12-01 19:45:38 UTC (rev 56)
@@ -222,6 +222,22 @@
 */
       var $_methods = array();
 /**
+ *  Flash Layout to use to allow custom layouts.
+ *  Defaults to the layout as used by $session->flash()
+ *
+ *  @var string
+ *  @access public
+ */
+       var $authFlashLayout = 'default';
+/**
+ *  Flash Error Params to use. Defaults to array() as used
+ *  by the Auth component preiviously
+ *
+ *  @var array
+ *  @access public
+ */
+       var $authFlashError = array();
+/**
 * Initializes AuthComponent for use in the controller
 *
 * @param object $controller A reference to the instantiating controller object
@@ -333,13 +349,13 @@
                               }
                       }

-                       $this->Session->setFlash($this->loginError, 'default', array(), 'auth');
+                       $this->Session->setFlash($this->loginError, $this->authFlashLayout, $this->authFlashError, 'auth');
                       $controller->data[$this->userModel][$this->fields['password']] = null;
                       return false;
               } else {
                       if (!$this->user()) {
                               if (!$this->RequestHandler->isAjax()) {
-                                       $this->Session->setFlash($this->authError, 'default', array(), 'auth');
+                                       $this->Session->setFlash($this->authError, $this->authFlashLayout, $this->authFlashError, 'auth');
                                       if (!empty($controller->params['url']) && count($controller->params['url']) >= 2) {
                                               $query = $controller->params['url'];
                                               unset($query['url'], $query['ext']);
@@ -403,7 +419,7 @@
                       return true;
               }

-               $this->Session->setFlash($this->authError, 'default', array(), 'auth');
+               $this->Session->setFlash($this->authError, $this->authFlashLayout, $this->authFlashError, 'auth');
               $controller->redirect($controller->referer(), null, true);
               return false;
       }

I hope this gives you some insight into how to handle these types of situations. Try to keep things flexible, and in the end, all will turn out, just how you want them!

Add Comment