Обработка ошибок в PHP - PullRequest
       14

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

30 голосов
/ 25 сентября 2008

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

Ответы [ 9 ]

31 голосов
/ 25 сентября 2008

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

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

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

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

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

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

24 голосов
/ 27 сентября 2008

Грубо говоря, ошибки являются наследием в 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);

Есть несколько случаев, когда код специально разработан для работы с ошибками. Например, метод schemaValidate для 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());
}
2 голосов
/ 26 сентября 2008

Лучшая практика ИМХО - использовать следующий подход: 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 ();

?>

2 голосов
/ 25 сентября 2008

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

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

2 голосов
/ 25 сентября 2008

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

Как правило, вы можете использовать блок 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 />');
1 голос
/ 27 сентября 2008

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

1 голос
/ 25 сентября 2008

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

http://us.php.net/manual/en/function.set-exception-handler.php
и
http://us.php.net/manual/en/function.set-error-handler.php

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

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

что-то может быть действительно не так.

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

1 голос
/ 25 сентября 2008

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

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

0 голосов
/ 18 ноября 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...