Обработка ошибок в PHP

Я знаком с некоторыми из основ, но то, о чем я хотел бы узнать больше, – это когда и почему обработка ошибок (включая исключения исключения) должна использоваться на PHP, особенно на реальном сайте или в веб-приложении. Это что-то, что можно переоценить, и если да, то как выглядит чрезмерное употребление? Существуют ли случаи, когда его нельзя использовать? Кроме того, каковы некоторые общие проблемы безопасности в отношении обработки ошибок?

Одна вещь, добавленная к уже сказанному, состоит в том, что важно, чтобы вы регистрировали любые ошибки в своем веб-приложении в журнале. Таким образом, как предлагает Джефф «Кодирование ужасов», говорит Этвуд, вы узнаете, когда ваши пользователи испытывают проблемы с вашим приложением (вместо того, чтобы «спрашивать их, что не так»).

Для этого я рекомендую инфраструктуру следующего типа:

  • Создайте таблицу «crash» в своей базе данных и набор классов-оболочек для сообщений об ошибках. Я бы рекомендовал установить категории для сбоев («блокировка», «безопасность», «ошибка / предупреждение PHP» (исключение) и т. Д.).
  • Во всем коде обработки ошибок обязательно запишите ошибку. Выполнение этого последовательно зависит от того, насколько хорошо вы создали API (выше шага) – должно быть тривиально записывать сбои, если все сделано правильно.

Дополнительный кредит: иногда ваши сбои будут сбоями на уровне базы данных: то есть сервер БД и т. Д. Если это так, ваша инфраструктура регистрации ошибок (выше) потерпит неудачу (вы не можете зарегистрировать аварийный сигнал в БД, потому что попытки журнала для записи в БД). В этом случае я бы написал логику отказоустойчивости в вашем классе оболочки Crash либо

  • отправьте электронное письмо администратору, и / ИЛИ
  • записывать сведения об аварии в текстовый файл

Все это звучит как излишество, но поверьте мне, это имеет значение, принято ли ваше приложение как «стабильное» или «слабое». Это различие связано с тем, что все приложения запускаются как разгромные / сбойные все время, но те разработчики, которые знают обо всех проблемах с их приложением, имеют возможность его исправить.

Грубо говоря, ошибки являются наследием PHP, в то время как исключения – это современный способ лечения ошибок. Самое простое – настроить обработчик ошибок, который выдает исключение. Таким образом, все ошибки преобразуются в исключения, а затем вы можете просто иметь дело с одной схемой обработки ошибок. Следующий код преобразует ошибки в исключения для вас:

function exceptions_error_handler($severity, $message, $filename, $lineno) { if (error_reporting() == 0) { return; } if (error_reporting() & $severity) { throw new ErrorException($message, 0, $severity, $filename, $lineno); } } set_error_handler('exceptions_error_handler'); error_reporting(E_ALL ^ E_STRICT); 

Однако есть несколько случаев, когда код специально разработан для работы с ошибками. Например, метод DomDocument вызывает предупреждения при проверке документа. Если вы конвертируете ошибки в исключения, он прекратит проверку после первого отказа. Несколько раз это то, что вы хотите, но при проверке документа вам действительно понадобятся все сбои. В этом случае вы можете временно установить обработчик ошибок, который собирает ошибки. Вот небольшой фрагмент, который я использовал для этой цели:

 class errorhandler_LoggingCaller { protected $errors = array(); function call($callback, $arguments = array()) { set_error_handler(array($this, "onError")); $orig_error_reporting = error_reporting(E_ALL); try { $result = call_user_func_array($callback, $arguments); } catch (Exception $ex) { restore_error_handler(); error_reporting($orig_error_reporting); throw $ex; } restore_error_handler(); error_reporting($orig_error_reporting); return $result; } function onError($severity, $message, $file = null, $line = null) { $this->errors[] = $message; } function getErrors() { return $this->errors; } function hasErrors() { return count($this->errors) > 0; } } 

И вариант использования:

 $doc = new DomDocument(); $doc->load($xml_filename); $validation = new errorhandler_LoggingCaller(); $validation->call( array($doc, 'schemaValidate'), array($xsd_filename)); if ($validation->hasErrors()) { var_dump($validation->getErrors()); } 

Неиспользуемые ошибки останавливают сценарий, это само по себе является довольно веской причиной для их обработки.

Как правило, вы можете использовать блок Try-Catch для устранения ошибок

 try { // Code that may error } catch (Exception $e) { // Do other stuff if there's an error } 

Если вы хотите остановить сообщение об ошибке или предупреждение, появившееся на странице, вы можете префикс вызова с помощью знака @ так.

  @mysql_query($query); 

С запросами, однако, как правило, неплохо сделать что-то подобное, чтобы вы лучше поняли, что происходит.

 @mysql_query($query) or die('Invalid query: ' . mysql_error() . '<br />Line: ' . __LINE__ . '<br />File: ' . __FILE__ . '<br /><br />'); 

Вы должны использовать обработку ошибок в случаях, когда у вас нет явного контроля над данными, над которыми работает ваш скрипт. Я часто использую его, например, в таких местах, как проверка формы. Знание того, как выявлять места, подверженные ошибкам в коде, требует некоторой практики: некоторые из них являются после вызовов функций, которые возвращают значение или при обработке результатов запроса базы данных. Вы никогда не должны предполагать, что возврат от функции будет тем, что вы ожидаете, и вы должны быть уверены, что код будет в ожидании. Вам не нужно использовать блоки try / catch, хотя они полезны. Много раз вы можете пройти с простой проверкой if / else.

Обработка ошибок идет рука об руку с безопасными методами кодирования, так как существует множество «ошибок», которые не приводят к простому сбою вашего сценария. в то время как не строго говоря об обработке ошибок как таковой, у добавленных байтов есть хорошая серия из 4 статей по некоторым основам безопасного программирования PHP, которые вы можете найти ЗДЕСЬ . Здесь есть много других вопросов о stackoverflow по таким темам, как mysql_real_escape_string и Regular Expressions, которые могут быть очень эффективны при подтверждении содержимого введенных пользователем данных.

Лучшая практика IMHO заключается в использовании следующего подхода: 1. создать обработчик ошибок / исключений 2. запустить его при запуске приложения 3. обрабатывать все свои ошибки изнутри

 <?php 

class Debug {

  public static setAsErrorHandler() { set_error_handler(array(__CLASS__, '__error_handler')); } public static function __error_handler($errcode, $errmsg, $errfile, $errline) { if (IN DEV) { print on screen } else if (IN PRO) { log and mail } } 

}

Debug :: setAsErrorHandler ();

?>

Вместо вывода mysql_error вы можете сохранить его в журнале. таким образом вы можете отслеживать ошибку (и вы не зависите от того, как пользователи сообщают об этом), и вы можете войти и устранить проблему.

Лучшая обработка ошибок – это тот вид, который прозрачен для пользователя, пусть ваш код справится с проблемой, не нужно привлекать этого пользователя.

помимо обработки ошибок сразу же в коде, вы также можете использовать

http://us.php.net/manual/en/function.set-exception-handler.php
а также
http://us.php.net/manual/en/function.set-error-handler.php

Я считаю, что ваш собственный обработчик исключений особенно полезен. Когда возникает исключение, вы можете выполнять разные операции в зависимости от типа исключения.

ex: когда вызов mysql_connet возвращает FALSE я выкидываю new DBConnectionException(mysql_error()) и обрабатываю его как «особый» способ: регистрировать ошибку, информацию о соединении с БД (хост, имя пользователя, пароль) и т. д. и, возможно, даже посылать по электронной почте команду разработчиков уведомив их, что что-то может быть действительно неправильно с БД

Я использую это, чтобы выполнить стандартную обработку ошибок. я бы не рекомендовал использовать этот подход

Подавление ошибок с помощью @ очень медленно.

Вы также можете использовать Google Forms для поиска и анализа исключений без необходимости поддерживать базу данных или общедоступный сервер. Здесь есть учебник, который объясняет процесс.