Forum Moderators: coopster

Message Too Old, No Replies

Why is this try . catch code not working?

try catch exception handling mysql

         

Tehuti

11:18 am on Oct 29, 2014 (gmt 0)

10+ Year Member Top Contributors Of The Month



Below is how I handle MySQL connection errors.

Basically, if the connection fails or if there's a MySQL error, the error is supposed to be logged and I am meant to be sent an e-mail. Obviously, I don't want to receive thousands of e-mails. Therefore, the e-mail is supposed to be sent only if it's been over 30 minutes (1,800 seconds) since the previous e-mail was sent. Everything works except the e-mail, which isn't sent. And I can't work out why.

The two variables ($last_modified and $time_elapsed) are set, but the e-mail just isn't sent. It's got something to do with the "if" statement. When I remove it, the code works.

Can you see the problem?

Any assistance will be much appreciated.


function handle_error($err) {
throw new Exception($err);
}
try {
$con = mysql_connect("", "", "") or handle_error("mysql_connect failed! ");
mysql_select_db("") or handle_error("mysql_select_db failed! ");
$sql = "SELECT blah blah blah ...";
$result = mysql_query($sql, $con) or handle_error("mysql_query failed! ");
}
catch(exception $e) {
// Log error in error-log.txt.
trigger_error($e->getMessage() . mysql_error(), E_USER_WARNING);
// Send yourself an email if more than 30 mins (1800 seconds) have passed since previous e-mail.
$last_modified = filemtime('error-log.txt');
$time_elapsed = time() - $last_modified;
if($time_elapsed > 1800) {
error_log($e->getMessage() . "Date: " . date("l jS \of F, Y, h:i:s A") . ". File: " . $_SERVER['REQUEST_URI'], 1, "example@aol.com", "From: example@yahoo.com");
}
}

penders

1:00 pm on Oct 29, 2014 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The two variables ($last_modified and $time_elapsed) are set...


...and the values are as expected, ie. $time_lapsed is > 1800? Otherwise there is nothing actually wrong with your IF statement itself. Where is "error-log.txt" located? You're not specifying any path information, so relying on the CWD.

You should also note that the result of filemtime() is cached (see: clearstatecache() [php.net]). (However, it should only be cached for the current request and if it was cached it would be returning an old timestamp, so you would only end up getting more errors emailed, not less.)

Bit of an aside, but... you seem to be going about this in a very long winded way: Calling a function on an error condition to throw an exception (so the "location" of the exception is always going to be this function) and then triggering an error in the catch block, sending the email, etc. This code would need to be wrapped around every code block you want to trap/log an error!? Have you considered a custom error/exception handler?

Tehuti

2:54 pm on Oct 29, 2014 (gmt 0)

10+ Year Member Top Contributors Of The Month



Thanks, Penders.

I can see the problem now. It's quite stupid of me. :-/

This is what the script's doing:


1) Whenever there's an error, log it in error-log.txt.

2) Check when error-log.txt was last modified (which would always be just a split second ago).

3) Send e-mail only if $last_modified > 1,800 (which it never is).


Even if I changed the order so that the e-mail is sent before the error is logged, the script is still flawed because it would not work if errors are constantly occurring. It would send the first e-mail and that's it; it won't send one every 30 minutes.

The only way around it is to check not when error-log.txt was last modified but instead to check when I last sent an e-mail.

Is it possible to check when I last sent an e-mail? I can't find anything online that says I can.

Tehuti

3:02 pm on Oct 29, 2014 (gmt 0)

10+ Year Member Top Contributors Of The Month



I've changed the order and it's still not sending an e-mail!

The file path is fine. I can echo $last_modified and $time_elapsed, both of which are set.

Really confused.

penders

3:13 pm on Oct 29, 2014 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



...which would always be just a split second ago


Dang! Missed that one - yes, of course! lol

Is it possible to check when I last sent an e-mail?


I think you would need to explicitly log when an email was last sent. And wrap your call to error_log() in another function to enable you to do this. This could be a very simple (and quick) log, perhaps consisting of just a timestamp:

file_put_contents('last-email-sent.log',time());


$last_sent = (int)file_get_contents('last-email-sent.log');

Tehuti

4:08 pm on Oct 29, 2014 (gmt 0)

10+ Year Member Top Contributors Of The Month



Thanks, Penders.

And thanks for clearstatcache().

And you're right, I probably am going about this in a long-winded way. I don't pretend to fully understand what I'm doing. I'm still learning.

However, I should make it clear that the above code is actually more complicated than what I have presented. It does other things. The try block tries it all and the catch block catches any errors.

As to your suggestion, would something like the following work?


$timeLastEmailWasSent = (int)file_get_contents('last-email-sent.txt');
$timeElapsed = time() - $timeLastEmailWasSent;
if($timeElapsed > 1800) {
error_log($e->getMessage() . "Date: " . date("l jS \of F, Y, h:i:s A") . ". File: " . $_SERVER['REQUEST_URI'], 1, "example@aol.com", "From: example@yahoo.com");
file_put_contents('last-email-sent.txt', time());
}

Some things I don't understand:

1) What does "(int)" do before file_get_contents()?

2) The last line adds the new time stamp to the file. Is it added to a new line in the file or does it replace the old time stamp?

3) If it adds the new time stamp to a new line, does (int)file_get_contents() always get the last line?

4) What is a .log file? How do I create one? Can't I just use a .txt file?

Tehuti

4:14 pm on Oct 29, 2014 (gmt 0)

10+ Year Member Top Contributors Of The Month



Sorry, I found the answers to (2) and (3). I should've just checked first.

Apparently, file_put_content() clears the existing content unless the parameter FILE_APPEND is set.

Tehuti

4:44 pm on Oct 29, 2014 (gmt 0)

10+ Year Member Top Contributors Of The Month



Yes! The code seems to work.

I ran this first:

file_put_contents('last-email-sent.log', time());

It created a .log file.

I then tried the code, and it worked.

penders

4:54 pm on Oct 29, 2014 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Yes, something like that should work.

1) The "(int)" explicitly type casts (converts) the return value of the file_get_contents() function (which is a string) to an integer. TBH it's not strictly necessary, since PHP will implicitly convert it to an integer on the next line. However, using "(int)" here is self-documenting and is more readable - it is obvious that an integer is expected.

4) ".log" is simply the file extension, you can call it anything you like. ".log" files are usually text files, just as ".txt" files are text files. I gave it a ".log" extension since it is generally more obvious that it is a computer generated (log) file. ".txt" files are more commonly human generated, although they can obviously be generated by anything. The Apache error log filename defaults to "error.log", but it's just an ordinary text file.

penders

5:00 pm on Oct 29, 2014 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



...and it worked.


Nice one!

Yes, you would otherwise get an E_WARNING if the log file didn't exist before trying to read it. It would perhaps be preferable to just check that the file exists before reading it (is_file()), rather than having to remember to first create it (a problem if you are distributing the software). You could also use error suppression (@ operator) - however - that is bad practise!

Tehuti

8:45 pm on Oct 29, 2014 (gmt 0)

10+ Year Member Top Contributors Of The Month



I appreciate the help, Penders. ;-)