Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

error handler to redirect page

Status
Not open for further replies.

progman1010

Programmer
Jan 2, 2008
108
US
Does anyone know of a quick and easy way to set_error_hander and have it redirect to a 'sorry, we've encountered an error...' page? I'm having trouble actually getting the redirect to work.

here's my code so far...
Code:
//my standard redirect function...
function redirect($url,$clear=false) {

	if (!$clear) { //if clear is true, then it will skip the session vars and all.
		//check for session first
		if ($_SESSION['redirect']!='') $url=$_SESSION['redirect'];

		//url request supercedes session var
		//use this for special overrides- allows for universal return pages
		if ($_REQUEST['redirect']!='') $url=$_REQUEST['redirect'];
	}

	//replace special chars so that you get less errors
	$url=str_replace('~','&',$url);

	unset($_SESSION['redirect']);  // clear

	if (substr($url,0,1)!="?") $url="?".$url;

	if (!headers_sent()) header("Location: index.php$url");
	else echo "<script>window.location=\"index.php$url\";</script><noscript>Javascript redirect didn't work.<br /><a href=\"$url\">Click here to go to this page.</a></noscript>";
}




//now, the error handler
error_reporting(0);

// define an assoc array of error string
// in reality the only entries we should
// consider are E_WARNING, E_NOTICE, E_USER_ERROR,
// E_USER_WARNING and E_USER_NOTICE
$errortype = array (
			E_ERROR              => 'Error',
			E_WARNING            => 'Warning',
			E_PARSE              => 'Parsing Error',
			E_NOTICE             => 'Notice',
			E_CORE_ERROR         => 'Core Error',
			E_CORE_WARNING       => 'Core Warning',
			E_COMPILE_ERROR      => 'Compile Error',
			E_COMPILE_WARNING    => 'Compile Warning',
			E_USER_ERROR         => 'User Error',
			E_USER_WARNING       => 'User Warning',
			E_USER_NOTICE        => 'User Notice',
			E_STRICT             => 'Runtime Notice',
			E_RECOVERABLE_ERROR  => 'Catchable Fatal Error'
			);

// user defined error handling function
function userErrorHandler($errno, $errmsg, $filename, $linenum, $vars) 
{
	global $errortype;
    // timestamp for the error entry
    $dt = date("Y-m-d H:i:s (T)");

    
    // set of errors for which a var trace will be saved
    $user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);
    
    $err = "<errorentry>\n";
    $err .= "\t<datetime>" . $dt . "</datetime>\n";
    $err .= "\t<errornum>" . $errno . "</errornum>\n";
    $err .= "\t<errortype>" . $errortype[$errno] . "</errortype>\n";
    $err .= "\t<errormsg>" . $errmsg . "</errormsg>\n";
    $err .= "\t<scriptname>" . $filename . "</scriptname>\n";
    $err .= "\t<scriptlinenum>" . $linenum . "</scriptlinenum>\n";

    if (in_array($errno, $user_errors)) {
        $err .= "\t<vartrace>" . wddx_serialize_value($vars, "Variables") . "</vartrace>\n";
    }
    $err .= "</errorentry>\n\n";
    
	
	if (!in_array($errno, array(E_NOTICE,E_USER_NOTICE))) {
	    // save to the error log, and e-mail me if there is a critical user error
    	error_log($err, 3, $doc_root."error.log");
       	//mail(ERROR_NOTIFICATION_EMAIL, "Critical User Error", $err);
		redirect("/index.php?content=error");
	} 
}

set_error_handler("userErrorHandler");
 
a few thoughts.

1. the $errno will not be a linear integer in the way that you can map to an array. the integer value of the error types can be found here
2. i cannot see anywhere that you have defined $doc_root or made the variable available to the function's scope. it is also not clear if the script has permissions to write to the relevant file as you don't test for is_writable.
3. you have not said what 'won't work' means. what exactly is not working?
4. the url, by the time it gets to the header statement, will look like this
Code:
/index.php?/index.php?content=error
does your script really parse this kind of url?

 
Good call jpadie ... I think $doc_root would be available if superglobals is on though, no?

Could also try an ob_start() ... ob_end_flush() then a header("Location: $url"); to redirect the user; the ob_* will clear any output buffer before redirecting.

Greg
 
yes, you could try output buffering but the code that the OP adopts for redirecting should be OK without output buffering (assuming javascript).

and grtammi, no, i don't think that $doc_root would be available under a register_globals environment. i think the nearest to it would be $DOCUMENT_ROOT from $_SERVER['DOCUMENT_ROOT']
 
you're right, i did make a couple of typos (changed redirect("?content=error"); and although should've been a made global, $doc_root wasn't even necessary). unfortunately, fixing those still didn't change my results, though...

I think the problem lies in the fact that I need to disable simple warnings (like variable wasn't defined) and allow fatal warnings (like function not defined, missing }, etc.). But they are both showing up as $errno=8.

Is there a way to drill down into the individual bits comprising the error number byte and get more specific as to how to handle it? The way the error numbers are laid out would lead me to believe that everything between decimal 8 and 15 would have a bitwise setting that means something... or am i just reaching for straws?

-J

 
each error type is different. there are no error types between those that are quoted on the list i referred you to.
 
Typically, error constants are defined so that when they are converted to binary they are distinct. For instance, PHP defines E_ERROR as 1, E_WARNING as 2 and E_NOTICE as 8 (for simplicity's sake, we'll stop there). When these are converted into a binary word, E_ERROR becomes 0001, E_WARNING becomes 0010, and E_NOTICE becomes 1000. That way you can define your values using a bitmask and use bitwise operations like && and || on them to get more detailed results.

That probably also requires an explanation.

Say you want to set your error level so that it shows errors and warnings, but not notices. PHP provides the function error_reporting() which takes an integer as its only argument. So, to get only errors and warnings, you would call the function as either:

Code:
error_reporting( E_ERROR || E_WARNING ); // preferred

or:

Code:
error_reporting(3); // not a good idea

and you would get the same results (for now, until the values of the constants change in a future version) because in both cases you are setting your "error bitmask" to the binary value 0011. The error handler then needs to to a bitwise comparison of the returned error value with the bitmask and if it returns anything greater than 0, raise an error.

I hope that helps. When I first started looking at bitmasks it took a long time before I was comfortable enough with them to try and actually use them.
 
ok. that makes a lot of sense. so how can i use that to distinguish between errors for what I need?

the problem i'm having (from what I can tell) is caused by two different area throwing the same error (8). I want to let warnings about undefined variables pass, but i want to catch errors about invalid functions.

is there a way to distinguish?
 
yes. test the value of errstring which for you is $errmsg.

i am very surprised that an 'invalid' function (whatever that is) is causing only a notice to be thrown. calling a function that doesn't exist should give a fatal error at parse time.
 
ok, so maybe i'm a little confused now.

am i not able to trap fatal errors? is that what's holding me up? You are correct, the undefined function throws a 'fatal error' message and then when i add to the handler function "die($errno)" it shows 8. Something seems inconsistent here.

Is trying to trap all errors like this a bad practice? (i mean, i'm not specifically trying to trap undefined functions, but I want to give potential errors a more user-friendly appeal than an ugly fatal error message)
 
you are not able to trap E_ERROR, no.
php manual said:
The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.

If errors occur before the script is executed (e.g. on file uploads) the custom error handler cannot be called since it is not registered at that time.

by the time you get to the error handler, it is not the E_ERROR that's being found, it's another error that's being reported.

by the way, it's good practice to kill the code execution expressly after a redirect. use die() or exit().
 
i know it's been a while since anything's been posted here, but thanks for the feedback. this all helped me figure out how to optimize my error trapping and it works "flawlessly" (so to speak!)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top