I am working on a site in a shared host. I don't have access to the PHP ini file, or the PHP ini_set
function, and I can't use php_flag
or php_value
directives.
I'm using the set_error_handler
function to log most errors, and trying to use the register_shutdown_function
to log fatal ones. I've tried several of the solutions for catching fatal errors here: How do I catch a PHP Fatal Error
. I can successfully use the solutions there to either display the errors on screen or bring up a custom error page, and to log non-fatal errors, but I can't seem to log the fatal errors.
This is simplest version of my attempts:
function errorHandler($num, $str, $file, $line) {
$now = strftime("%B %d, %Y at %I:%M %p", time());
$text = "{$now} → error {$num} in {$file}, line {$line}: {$str}\n";
$errorlog = "my_path/my_log";
$new = file_exists($errorlog) ? false : true;
if($handle = fopen($errorlog, 'a')) {
fwrite($handle, $text);
fclose($handle);
if($new) { chmod($errorlog, 0755); }
} else {
print("Could not open log file for writing"); //I'm using this to test
}
}
function fatalHandler() {
$error = error_get_last();
if($error) {
errorHandler($error["type"], $error["message"], $error["file"], $error["line"]);
}
}
set_error_handler("errorHandler");
register_shutdown_function("fatalHandler");
When I test this with a non-fatal error, like echo $undefined_variable
, it works and the error is logged properly. However if I test with a fatal error, like undefined_function()
, it does not log anything and prints "could not open log file". If I test with both errors present, it logs the non-fatal one, but not the fatal one.
Your question has been identified as a possible duplicate of another question. If the answers there do not address your problem, please edit to explain in detail the parts of your question that are unique.
@Vic Seedoubleyew -Well, the most obvious thing is the warning addressed in the question you mentioned failed to open stream: ...etc
has nothing to do with my situation. That warning never happened. The test message: "could not open log file for writing" is my own message that I wrote to myself, so I would have some evidence that the if
statement was being processed. I made that message up. It's noted very clearly in my question that the message is of my own making. Anyone experiencing the problem I was will never get the message failed to open stream...etc
, so they won't be helped by a question addressing a message they never got. I assume the point of all this is to actually help dummies like me.
The title: "Why does fopen
fail within a register shutdown function" was not my title. That is someone else's edit. My question was why I couldn't write to a log within the register_shutdown_function
. I didn't know whether fopen
was failing or there was some other problem. I was trying to log something out of the function and it wasn't working. Removing the stated goal (logging out of the function) from the question, and adding someone else's assessment "why does fopen
fail", actually makes it much less useful to anyone coming here for a solution to the situation I was experiencing. Had there already been a question present which addressed writing to a file within the shutdown function, I would have found it. "Why does fopen
fail" is too specific to be useful in a search by someone who doesn't know why they can't write to a file in the function.
I wasn't going to say anything about the edit, but since you have asked me to explain, I'm explaining. I realize everyone probably gets points for edits, but take a minute to consider the effect your edit has on the usefulness of the question to someone who comes here with the situation I had.