| Flash Your Errors: It's Illegal In 28 States! [message #2147] |
Thu, 31 July 2008 12:20 |
dcousineau Messages: 6 Registered: July 2008 Location: College Station |
Shiny and New |
|
|
I've often had problems in sites where I bounce requests around with losing error messages and having to trudge through the system error log looking for what exactly went wrong in my code.
For example, say for instance you submit a form to PageA.php. PageA.php, after crunching the POST data, decides to header('Location: PageB.php') redirect you to PageB.php. HOWEVER, PageA.php threw an error that did not interfere with the header() call that caused a bug that you are having a hard time tracing.
Here is where I bring up the concept of flash messages. Anyone familiar with CakePHP, Symfony, or the Zend Framework (and others) will be somewhat familiar with flash messages.
A flash message is a message (sometimes a string, in some cases just a variable store) that persists until it is read. Meaning if a page sets a flash message, the message will persist across page loads until the message is retrieved.
A more concrete example is a little flash messenger I wrote for myself:
class FlashMessenger
{
protected function __construct() { }
/**
* Adds a message to the flash message queue. Message can be of mixed type
*
* @param mixed $message
*/
public static function addMessage($message)
{
if( !isset($_SESSION) )
{
session_start();
}
if( isset($_SERVER['REQUEST_URI']) )
$uri = $_SERVER['REQUEST_URI'];
else
$uri = __FILE__;
$_SESSION['__lat_flashmessages'][] = array(
'URI' => $uri,
'message' => $message
);
}
/**
* Get stored messages from queue
*
* @return Array
*/
public static function getMessages()
{
if( !isset($_SESSION) )
{
session_start();
}
if( isset($_SESSION['__lat_flashmessages']) && is_array($_SESSION['__lat_flashmessages']) )
{
$messages = $_SESSION['__lat_flashmessages'];
unset($_SESSION['__lat_flashmessages']);
}
else
{
$messages = array();
}
return $messages;
}
}
You'll notice I store the messages in the session until I retrieve them (where I unset them as they have been read).
To solve our original problem, we use a flash messenger to store errors until we can display them. Meaning PageA.php sets the error in a flash message and PageB.php loads the message and displays it! The easiest way to do this overloading our Error and Exception handlers in some common location shared by every script (say a common.php or index.php):
function appErrorHandler($errno, $errstr, $errfile = "", $errline = -1, $errcontext = array())
{
FlashMessenger::addMessage(array(
'errno' => $errno,
'errstr' => $errstr,
'errfile' => $errfile,
'errline' => $errline,
'errcontext' => $errcontext
));
}
function appExceptionHandler(Exception $exception)
{
FlashMessenger::addMessage(array(
'exception' => $exception,
));
}
set_error_handler( "appErrorHandler" );
set_exception_handler( "appExceptionHandler" );
Now all we'd have to do is perform a FlashMessenger::getMessages(); on each page (obviously after any header() calls or it defeats the purpose) and either var_dump() it or format it to check out the errors.
Now when our code triggers an error but still successfully redirects, we can see the errors on the final page! (And with my class storing the REQUEST_URI of the page that adds the flash message, you'll easily be able to tell which page triggered what error should both PageA.php and PageB.php have issues!
Much thanks to my friend Chris Weldon (http://www.chrisweldon.net/) for this idea.
EDIT: s/Christ/Chris
[Updated on: Thu, 31 July 2008 12:34] Daniel Cousineau
Project Manager at Net Perspective, LLC.
My Blog of Pure Awesome
|
|
|