Jump to content

error_handler


kurt.santo

Recommended Posts

In my desperate attempt to build my own error_handler I created the file handle3.php as follows:

set_error_handler("my_error_handler");ob_start();function my_error_handler($errno, $errstr, $errfile, $errline) {$errLogLine = date("n/j/y H:i:s")." - ".$errfile.":".$errline.$contextENV.": ". $errstr."\n";        error_log ($errLogLine, 3, "errors.log");        exit;       echo ("Location: ok.php");        ob_end_clean();        exit;}ob_end_flush();

My error3.php file included the error handler in the first line via "<?php include('handle3.php');?>". Nothing happens. It neither logs anything, nor does it send the user to ok.php. Why is that? Please do not be offended if my code is horribly wrong. I just gather all online information I can find and put it somehow together (sometimes not even understanding all the workings of some scripts, although I thought this one was clear for me)...Kurt

Link to comment
Share on other sites

The error_log function probably needs an absolute path to the error log file. That's probably why it's not writing anything to a log file. It's not redirecting because right after you use error_log you exit. Also, if you want to redirect you need to use the header function. Also, you turn off output buffering right after you turn it on. You turn it on, then define your error handler function, then turn it right back off again. So by the time the error handler function gets called output buffering is already off.

Link to comment
Share on other sites

The error_log function probably needs an absolute path to the error log file. That's probably why it's not writing anything to a log file. It's not redirecting because right after you use error_log you exit. Also, if you want to redirect you need to use the header function. Also, you turn off output buffering right after you turn it on. You turn it on, then define your error handler function, then turn it right back off again. So by the time the error handler function gets called output buffering is already off.
The logging works now with the absolute path, cheers. Still having problems with redirection. Incorporated your hints as:
ob_start();function my_error_handler($errno, $errstr, $errfile, $errline) {$errLogLine = date("n/j/y H:i:s")." - ".$errfile.":".$errline.$contextENV.": ". $errstr."\n";        error_log ($errLogLine, 3, "C:\Dokumente und Einstellungen\Kurt\Eigene Dateien\errors.log");       header ("Location: ok.php");        ob_end_clean();}set_error_handler("my_error_handler");ob_end_flush();

In same context, I have two more questions: in error log file it gets quite difficult to read the error information without any line breaks. How would I adjust the error_log line to make each entry appear on one line? Also, once the site is live I would like to have the error log in "private" folder, which is on same level as my "web" folder. How would you write that path (or is it not possible)? Do not think it is a good idea to have logs available to anyone knowing what he/she is doing...Kurt

Link to comment
Share on other sites

I would remove the output buffering functions, the only thing that is getting buffered is the call to set_error_handler. By the time the error handler actually gets called buffering has since been turned off, so having ob_end_clean in the function might be a problem. After the header it would be good to use exit, after you send a location header it doesn't matter what else you send.

How would I adjust the error_log line to make each entry appear on one line?
Put a line break on the end of the message.
How would you write that path
Depends on the server, print the __FILE__ constant to see the path to the script that you have running, you can use that to figure out where you need to point to.
Link to comment
Share on other sites

I would remove the output buffering functions, the only thing that is getting buffered is the call to set_error_handler. By the time the error handler actually gets called buffering has since been turned off, so having ob_end_clean in the function might be a problem. After the header it would be good to use exit, after you send a location header it doesn't matter what else you send.Put a line break on the end of the message.Depends on the server, print the __FILE__ constant to see the path to the script that you have running, you can use that to figure out where you need to point to.
I removed all output buffering functions, but now it complains that headers have already been sent (although the file is included in first line with no space in between). The code for error handler is:
function my_error_handler($errno, $errstr, $errfile, $errline) {$errLogLine = date("n/j/y H:i:s")." - ".$errfile.":".$errline.$contextENV.": ". $errstr."\n";        error_log ($errLogLine, 3, "C:\Dokumente und Einstellungen\Kurt\Eigene Dateien\errors.log");       header ("Location: ok.php");        exit();}set_error_handler("my_error_handler");

and I include via:

<?php include('handle3.php');?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">

Why is that?I used "print (dirname(__FILE__)); " to get the location of the private folder, but when I use any reference as this it does not create any error file, not does it write to it when I put one in (worked on c: without any problems). Even when I use the path to my web directory as "/home/sites/jalp.co.uk/web/testing/errorHandling" it does not do it. Why is that?Sorry to be such a pain again. Kind of getting there...Kurt

Link to comment
Share on other sites

If you want to use output buffering you'll need the ob_end function at the very end of the page instead of in the include file. So either do buffering for the entire page or remove the location header in the error handler, but you can't buffer only the include file (there's no output to buffer). For the log file, check that the permissions on the folder you're trying to write to are set properly. You might just want to make a short script to create a new file and write some text to it where you want the log to go to check for errors.

Link to comment
Share on other sites

If you want to use output buffering you'll need the ob_end function at the very end of the page instead of in the include file. So either do buffering for the entire page or remove the location header in the error handler, but you can't buffer only the include file (there's no output to buffer). For the log file, check that the permissions on the folder you're trying to write to are set properly. You might just want to make a short script to create a new file and write some text to it where you want the log to go to check for errors.
I have done what you said and finally the thing works, which is great. If you don't mind, it would be great if you could explain further two things (for my learning curve):I use now the following in my page with no output buffering in the error handler
<?php ob_start();include('handle3cor.php');?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>Error php</title></head><body><?phpecho $variable;$result=200/0;?></body></html><?php ob_end_flush();;?>

It this correct? Although it is working just want to make sure it is all set up properly (obviously without the extra mistakes).Then, the error handler:

function my_error_handler($errno, $errstr, $errfile, $errline) {$errLogLine = date("n/j/y H:i:s")." - ".$errfile.":".$errline.$contextENV.": ". $errstr."\n";        error_log ($errLogLine, 3, "/home/sites/jalp.co.uk/web/errorNew.log");       header ("Location: sorry.php");        exit();}set_error_handler("my_error_handler");

logs any errors to my log file and redirects when an error occurs (working well;-)). As I have not specified any error types is this then for all error types? Would I need to make adjustments? Would like to make the most of your useful advice...Kurt

Link to comment
Share on other sites

That will handle all error types that PHP sends to a custom error handler, some errors like E_ERROR (a fatal error) it won't send there.
That's great, cheers.One more question in context with output buffering. I had the "headers already sent" problem before on some other files, so I put code for include files etc right at the top. This makes it impossible in Dreamweaver (which I use a lot) to modify pages site-wide. You cannot place editable regions in template files before the actual html starts. Would it be ok to use on all files "ob_start(); at top of file and ob_end_flush(); at end" to counteract the "header sent already" problem while having all necessary code for include files etc in header for example (before title as I need data from include files)?Kurt
Link to comment
Share on other sites

You can either use output buffering or just structure your code so that it sends any necessary headers before it starts the output.
I tried to put the relevant code for output buffering in my final file, but it complains "Parse error: syntax error, unexpected T_STRING in C:\Programme\Apache Software Foundation\Apache2.2\htdocs\web\about.php on line 4". This is the line where the session starts. The whole code right at top of my file is:
<?phpob_start();include('handle.php')session_start();$def_lang = 'en';$lang = (ereg('[a-z]{2}(\-[a-z]{2})?', $_GET['lang']) && is_file("{$_GET['lang']}/nav/globalNav.htm") ? $_GET['lang'] : (isset($_SESSION['lang']) ? $_SESSION['lang'] : $def_lang));$_SESSION['lang'] = $lang;$globalNav = "{$lang}/nav/globalNav.htm";$localNav = "{$lang}/nav/aboutNav.htm";$articleNav = "{$lang}/nav/articlesNav.htm";$furtherNav = "{$lang}/nav/furtherNav.htm";$content = "{$lang}/content/about.php";include $content;?>

What am I doing wrong? Also, I did not really understand what it means to "structure code so that it sends any necessary headers before it starts the output". Could you explain?Kurt

Link to comment
Share on other sites

You're missing a semicolon in that code.

Also, I did not really understand what it means to "structure code so that it sends any necessary headers before it starts the output". Could you explain?
Most applications do all of the PHP processing that the page needs before sending any output. You're sending some output, then doing a little processing, then some more output, then more processing, etc. You can reorganize your code so that all of the processing takes place before you decide whether or not you want to redirect, or show content, or whatever.
Link to comment
Share on other sites

You're missing a semicolon in that code.Most applications do all of the PHP processing that the page needs before sending any output. You're sending some output, then doing a little processing, then some more output, then more processing, etc. You can reorganize your code so that all of the processing takes place before you decide whether or not you want to redirect, or show content, or whatever.
Thank you for your input. Put the semicolon in and was surprised that I got transfered to the "problem page" as I thought the code was ok. Looking in the error log it says "Undefined index: lang" in line 6, which is the following line:
$lang = (ereg('[a-z]{2}(\-[a-z]{2})?', $_GET['lang']) && is_file("{$_GET['lang']}/nav/globalNav.htm") ? $_GET['lang'] : (isset($_SESSION['lang']) ? $_SESSION['lang'] : $def_lang));

Why does it say that lang is undefined? And what would you suggest?With the explanation of PHPs processing what would I look for if I searched for more info on that? I still didn't get it completely...Kurt

Link to comment
Share on other sites

If there is no lang variable on the querystring then $_GET['lang'] will be undefined. You can use isset to check for that.

$lang = (isset($_GET['lang']) && ereg('[a-z]{2}(\-[a-z]{2})?', $_GET['lang']) && is_file("{$_GET['lang']}/nav/globalNav.htm") ? $_GET['lang'] : (isset($_SESSION['lang']) ? $_SESSION['lang'] : $def_lang));

You can expand that into a normal if/else structure like this:

if (isset($_GET['lang']) && ereg('[a-z]{2}(\-[a-z]{2})?', $_GET['lang']) && is_file("{$_GET['lang']}/nav/globalNav.htm"))  $lang = $_GET['lang'];elseif (isset($_SESSION['lang']))  $lang = $_SESSION['lang'];else  $lang = $def_lang;

Both of those do the same thing.

Link to comment
Share on other sites

If there is no lang variable on the querystring then $_GET['lang'] will be undefined. You can use isset to check for that.
justsomeguy,Understood! I used your second option and works well...A last question in this thread (at least from my side): At top of my file I have the following code now:
<?phpob_start();include('error/handle.php');session_start();$def_lang = 'en';if (isset($_GET['lang']) && ereg('[a-z]{2}(\-[a-z]{2})?', $_GET['lang']) && is_file("{$_GET['lang']}/nav/globalNav.htm"))  $lang = $_GET['lang'];elseif (isset($_SESSION['lang']))  $lang = $_SESSION['lang'];else  $lang = $def_lang;$_SESSION['lang'] = $lang;$globalNav = "{$lang}/nav/globalNav.htm";$localNav = "{$lang}/nav/aboutNav.htm";$articleNav = "{$lang}/nav/articlesNav.htm";$furtherNav = "{$lang}/nav/furtherNav.htm";$content = "{$lang}/content/about.php";include $content;?>

Would it be more efficient to put the session related code in its own include file or is this not a good idea? Wonder how is most efficient way to structure the code...Kurt

Link to comment
Share on other sites

It will be most efficient if any code that is used on more then one page is in an include file that you can include wherever you need it.
Will put
ob_start();include('error/handle.php');session_start();$def_lang = 'en';if (isset($_GET['lang']) && ereg('[a-z]{2}(\-[a-z]{2})?', $_GET['lang']) && is_file("{$_GET['lang']}/nav/globalNav.htm"))  $lang = $_GET['lang'];elseif (isset($_SESSION['lang']))  $lang = $_SESSION['lang'];else  $lang = $def_lang;$_SESSION['lang'] = $lang;

in include file and insert first thing in files...Great input, cheers!Kurt

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...