Я хотел бы иметь возможность перехватывать сообщения die()
и exit()
. Это возможно? Я надеюсь на что-то похожее на set_error_handler
и set_exception_handler
. Я просмотрел register_shutdown_function()
но, похоже, не содержит контекста для вызовов die()
и exit()
.
Я понимаю, что die()
и exit()
– это плохие способы обработки ошибок. Я не хочу, чтобы мне сказали не делать этого. 🙂 Я создаю общую систему и хочу быть в состоянии изящно log exit()
и die()
если по какой-то причине кто-то (а не я) решает, что это хорошая идея.
Согласно руководству PHP , функции выключения должны быть уведомлены, когда вызывается функция die () или exit ().
Функции выключения и деструкторы объектов всегда будут выполняться, даже если вызывается exit ().
Кажется, что невозможно получить статус, отправленный в exit ($ status). Если вы не можете использовать буферизацию вывода для ее захвата, но я не уверен, как вы узнаете, когда нужно вызвать ob_start()
.
Да, вы можете, но вам нужны ob_start , ob_get_contents , ob_end_clean и register_shutdown_function
function onDie(){ $message = ob_get_contents(); // Capture 'Doh' ob_end_clean(); // Cleans output buffer callWhateverYouWant(); } register_shutdown_function('onDie'); //... ob_start(); // You need this to turn on output buffering before using die/exit @$dumbVar = 1000/0 or die('Doh'); // "@" prevent warning/error from php //... ob_end_clean(); // Remember clean your buffer before you need to use echo/print
Может быть, override_function () может быть интересным, если APD доступен
Насколько я могу судить, это действительно невозможно. Некоторые из решений, размещенных здесь, могут работать, но они требуют много дополнительной работы или многих зависимостей. Невозможно легко и надежно зафиксировать сообщения die () и exit ().
Почему вместо использования пользовательской обработки ошибок? Если нет, вы всегда можете использовать LD_PRELOAD и C Code injection, чтобы поймать его 🙂 Или перекомпилируйте php с настройками: P
Если вы используете метод одиночной точки входа. (index.php) Я могу порекомендовать это для обработки ошибок:
Укороченная версия:
ob_start(); register_shutdown_function('shutdownHandler'); include('something'); define(CLEAN_EXIT, true); function shutdownHandler() { if(!defined("CLEAN_EXIT") || !CLEAN_EXIT) { $msg = "Script stopped unexpectedly: ".ob_get_contents(); //Handle premature die()/exit() here } }
вob_start(); register_shutdown_function('shutdownHandler'); include('something'); define(CLEAN_EXIT, true); function shutdownHandler() { if(!defined("CLEAN_EXIT") || !CLEAN_EXIT) { $msg = "Script stopped unexpectedly: ".ob_get_contents(); //Handle premature die()/exit() here } }
-ob_start(); register_shutdown_function('shutdownHandler'); include('something'); define(CLEAN_EXIT, true); function shutdownHandler() { if(!defined("CLEAN_EXIT") || !CLEAN_EXIT) { $msg = "Script stopped unexpectedly: ".ob_get_contents(); //Handle premature die()/exit() here } }
Дополнительные шаги и более подробные сведения:
Примерно мой способ сделать это. Я еще больше занимаюсь тем, что я показываю здесь (обработка транзакций базы данных / откат / отправка электронной почты / запись журналов / отображение дружественных сообщений об ошибках / сообщений об ошибках пользователей и т. Д.), Но это основная идея всего этого).
Надеюсь, это поможет кому-то.
<?php //Some initialization //starting output buffering. (fatalErrorHandler is optional, but I recommend using it) ob_start('fatalErrorHandler'); //Execute code right at the end. Catch exit() and die() here. But also all other terminations inside PHPs control register_shutdown_function('shutdownHandler'); //handling other errors: Also optional set_error_handler('errorHandler'); try { //Include of offensive code include(...); } catch (Exception $ex) { //Handling exception. Be careful to not raise exceptions here again. As you can end up in a cycle. } //Code reached this point, so it was a clean exit. define(CLEAN_EXIT, true); //Gets called when the script engine shuts down. function shutdownHandler() { $status = connection_status(); $statusText = ""; switch ($status) { case 0: if (!defined("CLEAN_EXIT") || !CLEAN_EXIT) { $msg = "Script stopped unexpectedly: ".ob_get_contents(); //Handle premature die()/exit() here } else { //Clean exit. Just return return; } case 1: $statusText = "ABORTED (1)"; break; case 2: $statusText = "TIMEOUT (2)"; break; case 3: $statusText = "ABORTED & TIMEOUT (3)"; break; default : $statusText = "UNKNOWN ($status)"; break; } //Handle other exit variants saved in $statusText here } // error handler function (This is optional in your case) function errorHandler($errno, $errstr, $errfile, $errline) { $msg = "[$errno] $errstr\nOn line $errline in file $errfile"; switch ($errno) { case E_ERROR: $msg = "[E_ERROR] ".$msg; break; case E_WARNING: $msg = "[E_WARNING] ".$msg; break; case E_PARSE: $msg = "[E_PARSE] ".$msg; break; case E_NOTICE: $msg = "[E_NOTICE] ".$msg; break; case E_CORE_ERROR: $msg = "[E_CORE_ERROR] ".$msg; break; case E_CORE_WARNING: $msg = "[E_CORE_WARNING] ".$msg; break; case E_COMPILE_ERROR: $msg = "[E_COMPILE_ERROR] ".$msg; break; case E_COMPILE_WARNING: $msg = "[E_COMPILE_WARNING] ".$msg; break; case E_USER_ERROR: $msg = "[E_USER_ERROR] ".$msg; break; case E_USER_WARNING: $msg = "[E_USER_WARNING] ".$msg; break; case E_USER_NOTICE: $msg = "[E_USER_NOTICE] ".$msg; break; case E_STRICT: $msg = "[E_STRICT] ".$msg; break; case E_RECOVERABLE_ERROR: $msg = "[E_RECOVERABLE_ERROR] ".$msg; break; case E_DEPRECATED: $msg = "[E_DEPRECIATED] ".$msg; break; case E_USER_DEPRICIATED: $msg = "[E_USER_DEPRICIATED] ".$msg; break; default: $msg = "[UNKNOWN] ".$msg; break; } //Handle Normal error/notice/warning here. $handled = ... if ($handled) return true; //handled. Proceed execution else throw Exception($msg); //Be careful. this might quickly become cyclic. Be sure to have code that catches and handles exceptions. Else die() here after logging/reporting the error. } function fatalErrorHandler(&$buffer) { $matches = null; //Checking if the output contains a fatal error if (preg_match('/<br \/>\s*<b>([^<>].*)error<\/b>:(.*)<br \/>$/', $buffer, $matches) ) { $msg = preg_replace('/<.*?>/','',$matches[2]); //Handle Fatal error here return "There was an unexpected situation that resulted in an error. We have been informed and will look into it." } //No fatal exception. Return buffer and continue return $buffer; }
yes: напишите функцию и используйте это вместо этого.
function kill($msg){ // Do your logging.. exit($msg); }