Решил замутить debugger, работает, но вот Error Control Operator @ не хочет скрывать ошибки. Как узнать, был ли использован оператор @? Результат работы скрипта debugger.sphp PHP: <?php abstract class debugger { /** * Записывать ошибки в лог */ const LOG_USE = true; /** * Записывать дату, при записи в лог */ const DATE_USE = false; /** * Формат даты, записываемой в лог */ const DATE_TIME = 'Y-m-d H:i:s'; /** * Использовать трасировку ошибок */ const TRACING = true; /** * Буффер ошибок * * @var <string> */ private static $stderr = NULL; /** * Буффер вывода * * @var <string> */ private static $stdout = NULL; /** * Отладчик инициализирован * * @var <bool> */ private static $inited = false; /** * Вывод буфферизируется * * @var <bool> */ private static $output_hooked = false; /** * Возвращает тип ошибки по её коду * * @param $errno <int> Номер ошибки * @return <string> Тип ошибки */ private function error_type($errno) { $constants = get_defined_constants(true); $matches = array(); $array = array(); if(isset($constants['Core'])) $array = $constants['Core']; else if(isset($constants['internal'])) $array = $constants['internal']; if(!empty($array)) { foreach($array AS $key => $value) { if(!preg_match('/^E_(.+)$/', $key, $matches) || $value != $errno) continue; return str_replace('_', ' ', 'PHP_'.$matches[1]); } } return; } /** * Включает/выключает буфферизацию вывода * * @param $hook <bool> true - включить, false - выключить * @return <void> Метод ничего не возвращает */ public function output_hook($hook) { if(self::$output_hooked xor $hook) { ($hook) ? ob_start(array(__CLASS__, 'output_handler')) : ob_end_clean(); self::$output_hooked = (bool) $hook; } } /** * Обработчик вывода. * Дописывает строку $buffer в строку self::$stdout * и очищает стандартный буффер вывода * * @param $buffer <string> Часть буффера * @return <void> Метод ничего не возвращает */ public function output_handler($buffer) { self::$stdout .= $buffer; return ""; } /** * Обработчик ошибок. * Создаёт строку с описанием ошибки * * @param $errno <int> Код типа ошибки * @param $errstr <string> Описание ошибки * @param $errfile <string> Путь до файла, в котором произошла ошибка * @param $errline <int> Номер строки, в которой произошла ошибка * @return <void> Метод ничего не возвращает */ public function error_handler($errno, $errstr, $errfile, $errline) { $errtype = self::error_type($errno); self::error_message("$errtype: $errstr in $errfile on line $errline"); if(self::TRACING) { $backtrace = debug_backtrace(); array_shift($backtrace); for($i=0; $i<count($backtrace); $i++) { $err = $backtrace[$i]; $args = NULL; if(isset($err['args'])) { for($a=0; $a<count($err['args']); $a++) { $args .= ($args) ? ', '.$err['args'][$a] : $err['args'][$a]; } } $method = isset($err['class']) ? "{$err['class']}{$err['type']}" : NULL; $message = "[$i] {$method}{$err['function']}($args) "; $message .= "in {$err['file']} on line {$err['line']}"; self::error_message($message); } } } /** * Запись ошибок. * Записывает сообщение в лог и в self::$stderr * * @param $message <string> Сообщение * @return <void> Метод ничего не возвращает */ private function error_message($message) { self::$stderr .= str_replace($_SERVER['DOCUMENT_ROOT'], '', $message).PHP_EOL; if(self::LOG_USE) { if(self::DATE_USE) $message = '['.date(self::DATE_TIME).'] '.$message; error_log($message); } } /** * Инициализирует работу этого класса. * Устанавливает обработку ошибок через функцию self::error_handler, * регистрирует завершение работы скрипта через функцию self::shutdown, * включает буфферизацию вывода через функцию self::output_handler, * изменяет значение переменной self::$inited на истина * * @return <void> Метод ничего не возвращает */ public function init() { if(!self::$inited) { set_error_handler(array(__CLASS__, 'error_handler'), E_ALL); register_shutdown_function(array(__CLASS__, 'shutdown')); self::output_hook(true); self::$inited = true; } } /** * Обработчик завершения работы скрипта. * Выключает буфферизацию вывода через функцию self::output_handler, * выводит содержимое self::$stdout. * Если во время работы скрипта произошли ошибки, * отправляет клиенту заголовок статуса "HTTP/1.0 500 Internal Server Error". * Если включен вывод ошибок (display_errors), * клиент получает полную информацию о ошибках * * @return <void> Метод ничего не возвращает */ public function shutdown() { self::output_hook(false); if(!empty(self::$stderr)) { $display = @ini_get('display_errors'); $message = ($display != 'stderr' && $display != false) ? self::$stderr : NULL; header($_SERVER['SERVER_PROTOCOL'].' 500 Internal Server Error'); header('Content-Type: text/html; charset=utf-8'); echo "<h1>500 Internal Server Error</h1>"; echo "<pre>$message</pre>"; } else echo self::$stdout; } } ?> run.sphp PHP: <?php ini_set('display_errors', 'stdout'); header('Content-Type: text/plain; charset=utf-8'); require_once('debugger.sphp'); debugger::init(); @file_get_contents('notfound_file.php'); // Несуществующий файл ?>
Как всегда, разобрался сам нужно было добавить в error_handler: Код (Text): if(error_reporting() == 0) return false; т.к. error_reporting() изменяется на 0, в том местом где стоит @ Что собственно и сделал: PHP: <?php ... public function error_handler($errno, $errstr, $errfile, $errline) { if((error_reporting() & $errno) == 0) return false; ... ?>
Ну например 1) в стандартном error_handler нет трассировки и это сильно затрудняет отладку, уже запущенного в свет, проекта. 2) клиент должен знать, что произошла ошибка, а не просто получать неполную страницу. 3) к скрипту можно прикрутить функцию отправки письма на e-mail разработчика, в содержимое можно включить не только трассировку, но и значения $_SERVER, $_POST, $_GET, $_SESSION
Апельсин Кстати, верно. Ошибка в бизнес-логике обычно приводит к лавине ошибок, которая заканчивается каким-нибудь фаталом. А если посещаемость хотя-бы 1000 хитов в сутки...
Ясно. Видимо для этой цели придется отдельный скрипт писать Скажите, что нибудь по коду. Пока мне ясно, что это лучше в отдельный инклуд вынести: PHP: <?php ... header($_SERVER['SERVER_PROTOCOL'].' 500 Internal Server Error'); header('Content-Type: text/html; charset=utf-8'); echo "<h1>500 Internal Server Error</h1>"; echo "<pre>$message</pre>"; ... ?>