Правильная работа с исключениями в PHP / Хабр

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

  1. Исключения — это гибкий, расширяемый метод обработки ошибок;
  2. Это стандартизованный механизм – человеку, не работавшему с вашим кодом, не нужно будет читать мануал, чтобы понять, как обрабатывать ошибки. Ему достаточно знать, как работают исключения;
  3. С исключениями гораздо проще находить источник ошибок, так как всегда есть стек вызовов (trace).
Сразу скажу, что в этой статье я не открываю Америку. Описаны стандартные принципы работы с исключениями плюс некоторые особенности, налагаемые PHP. Полезно будет почитать новичкам, хотя может быть и опытные разработчики найдут что-нибудь новое для себя.

1. Никогда не бросайте абстрактное исключение (т.
е. просто Exception). Объявите хотя бы один класс исключений специально для вашего приложения (модуля, библиотеки)

class baseException extends Exception{}
и замените все строки в своем коде

throw new Exception();
на

throw new baseException();
Таким образом, все исключения вашего кода можно будет отличить от исключений не вашего кода.

2. Исключения должны быть иерархичны. У вас должен быть базовый класс исключений, от которого наследуются все исключения, бросаемые в вашем коде. Например, у вас в коде есть модуль для работы с файлами fileModule, объявите исключение, которое будет бросаться только этим модулем

class fileModuleException extends baseException{}
Если вам нужна еще бОльшая различимость ошибок, например, среди всех ошибок, связанных с работой с файлами, вы хотите различать ситуацию, когда файл не найден, то нужно объявить еще одно исключение

class fileNotFoundException extends fileModuleException{}
 
Соблюдая иерархичность, вы сможете различать исключения от разных модулей в вашем приложении. Я не призываю наплодить кучу исключений, для каждого модуля. Исключения должны проектироваться не от кода, а от ситуаций, которые вы хотите по-особенному обработать.
И обратная ситуация, не скупитесь сделать разные исключения, если того требует обстоятельства

try{
    //…
}catch(fileModuleException $e){
    switch($e->getCode()){//так делать не надо
        case 1: echo ‘file not found’;
        case 2: echo ‘file not readable’;
        //…
    }
}
 
Чтобы такие ситуации в принципе не были возможны, можно «заглушить» code в базовом классе

function __construct($message = », $code = 0) {
    parent::__construct($message, 0);
}

3. Не обрабатывайте исключения, если в данном контексте не понятно, как его обработать. Например, если вы следуете паттерну MVC, то в методе модели может быть не понятно, как обработать ошибку — как ее вывести, потому как за логику отвечает control, а за вывод view. Если не понятно, что делать с исключением, то «пробросьте» его дальше.

try{
    $db->begin();
    //…
    $db->commit();
}catch(Exception $e){
    $db->rollback();
    throw $e;
}
От метода, который пробрасывает исключения, можно ожидать любых исключений. Можно сузить количество исключений, бросаемых методом, преобразовав исключение:

try{
    //…
}catch(Exception $e){
    throw new baseException($message, 0, $e);//не разрывайте цепь
}
Тут очень важный момент — не разрывать цепь исключений. Третьим параметром передается изначальное исключение. Этот код нативно работает в 5.3 и с доработкой в 5.2. При таком подходе стек вызовов будет «цельным» от самого первого броска исключения.

4. У вас должен быть глобальный обработчик исключений. Это может быть или try…catch на самом верхнем уровне или ExceptionHandler.

Все исключения, которые добрались до глобального обработчика, считаются критическими, так как не были правильно обработаны ранее. Их надо залогировать.

5. Исключение это объект, соответственно его можно расширять под свои потребности. Допустим у вас многоязычное приложение и текст ошибки в бросаемом исключении нужно выводить пользователю. Соответственно это сообщение нужно переводить. Это не сложно, если сообщение без переменных частей, например, «Ошибка при выполнении операции». Но что делать, если в сообщение входят переменные части, например, «У вас недостаточно денег на балансе (1000). Нужно 2000». Тогда можно отдельно передать шаблон текста ошибки и отдельно сами переменные. Пример кода

Старый пример кода.

6. Преобразуйте все ошибки утверждений (assertion fail) и не фатальные ошибки в исключения (см. мою предыдущую статью)

7. Никогда не глушите исключения без какой либо обработки

try {
    //. ..
} catch (Exception $e) {
    //ничего делаем
}
 
потому, что в противном случае ошибку из-за таких действий будет очень сложно найти. Нужно хотя бы логировать:

try {
    //…
} catch (Exception $e) {
    exceptionHandlerClass::exceptionLog($e);
}

8. Документируйте исключения. Указывайте в докблоке, какие исключения выбрасывает метод (таг @throws, можно указывать больше одного). Это упростит всем жизнь.

Вот в принципе и все, что нужно знать про исключения. Еще один интересный факт напоследок — исключения можно ловить по интерфейсу:

interface iException{}
class customException extends baseException implements iException{}
try{
    //…
}catch(iException $e){
    //…
}

UPD исправлены замечания в комментариях:1, 2 и 3 (спасибо всем, кто поучаствовал в обсуждении).

Отдельное спасибо, хабраюзеру ckopobapkuh за активное участие

Урок 15.

PHP — ООП. Обработчик ошибок (error handler). Исключения (exceptions)
  • Главная >
  • Видео канал >
  • Урок 15. PHP — ООП. Обработчик ошибок (error handler). Исключения (exceptions)

УЛУЧШАЙТЕ НАВЫКИ С ПОМОЩЬЮ ПРАКТИКУМА

СЛЕДУЮЩЕЕ

15й урок курса из 16ти уроков. Курс подойдет новичкам, которые хотят максимально быстро въехать в современные принципы программирования на php. Разбираем механизм обработки ошибок в php. Говорим об исключениях.

Please enable JavaScript to view the comments powered by Disqus.

Регистрация через

или E-mail

Нажав на кнопку «Зарегистрироваться»,
Вы соглашаетесь с условиями использования.

Уже есть аккаунт

Получите курс бесплатно

Вы выбрали курс для изучения
«»
Чтобы получить доступ к курсу, зарегистрируйтесь на сайте.

РЕГИСТРАЦИЯ

Спасибо за регистрацию

Перейдите на почту и подтвердите Ваш аккаунт,
чтобы получить доступ ко всем
бесплатным урокам и вебинарам на сайте ITVDN. com

ПОДТВЕРДИТЬ ПОЧТУ НАЧАТЬ ОБУЧЕНИЕ

Спасибо за регистрацию

Ваш аккаунт успешно подтвержден.
Начать обучение вы можете через Личный кабинет
пользователя или непосредственно на странице курса.

НАЧАТЬ ОБУЧЕНИЕ

Подтверждение аккаунта

На Ваш номер телефона было отправлено смс с кодом активации аккаунта. Пожалуйста, введите код в поле ввода.

Отправить код еще раз

Изменить номер телефона

Ошибка

PHP: Исключение — вручную

Изменение языка: английскийбразильский португальскийкитайский (упрощенный)французскийнемецкийяпонскийрусскийиспанскийтурецкийДругое

Отправить запрос на вытягивание Сообщить об ошибке

(PHP 5, PHP 7, PHP 8)

Введение

Исключение — это базовый класс для все пользовательские исключения.

Обзор класса

класс Исключение реализует Метательный {

защищено нить $ сообщение =»»;

частный нить $ строка =»»;

защищенный инт $ код ;

защищенный нить $ файл =»»;

защищенный инт $ строка ;

частный множество $ трассировка = [];

частный ? Бросаемый $ предыдущий = ноль;

public __construct(string $message = «», int $code = 0,? Throwable $previous = null )

final public getMessage(): string

окончательный публичный getPrevious(): ?Throwable

final public getCode(): int

final public getFile(): string

final public getLine(): int

final public getTrace(): array

final public getTraceAsString(): string

открытый __toString(): строка

частный __clone(): недействительный

}

Свойства

сообщение

Сообщение об исключении

код

Код исключения

файл

Имя файла, в котором было создано исключение

строка

Строка, в которой было создано исключение

предыдущий

Предыдущее исключение

струна

Строковое представление трассировки стека

след

Трассировка стека в виде массива

Table of Contents

  • Exception::__construct — создание исключения
  • Exception::getMessage — получение сообщения об исключении Код исключения
  • Exception::getFile — Получает файл, в котором было создано исключение
  • Exception::getLine — Получает строку, в которой было создано исключение
  • Exception::getTrace — Получает трассировку стека
  • Exception::getTraceAsString — Получает трассировку стека в виде строки
  • Exception::__toString — Строковое представление исключения
  • Exception::__clone — Клонирование исключения

добавить примечание

Пользовательские заметки 3 заметки

вверх

вниз

96

Whysteepy на Gmail точка com

5 лет назад

Списки Throwable и дерева исключений по состоянию на 7. 2.0

    Error
      ArithmeticError
        DivisionByZeroError
      AssertionError
      ParseError
        TypeError
        ArgumentCountError
   Exception
      ClosedGeneratorException
      DOMException
      ErrorException
                        IntlException
      LogicException
          BadFunctionCallException
          BadMethodC allException
        DomainException
        InvalidArgumentException
        LengthException
        OutOfRangeException
        PharException
      ReflectionException
      RuntimeException
          OutOfBoundsException
                      OverflowException
        PDOException 90 . 4d1ca980848e6a
https ://3v4l.org/sDMsv

размещено кем-то здесь http://php.net/manual/en/class.throwable.php

вверх

вниз

36

cHao

8 лет назад

Обратите внимание, что свойства исключения заполняются при *создании* исключения, а не при его создании. Бросание исключения, похоже, не изменяет их.

Среди прочего это означает:

* Исключение будет винить строку, которая его создала, а не строку, которая его выдала.

* В отличие от некоторых других языков, повторное создание исключения не портит трассировку.

* Сгенерированное и не сгенерированное исключение выглядят в основном одинаково. На моей машине единственное видимое отличие состоит в том, что выброшенное исключение имеет свойство `xdebug_message`, а не выброшенное – нет. Конечно, если у вас не установлен xdebug, вы даже этого не получите.

вверх

вниз

5

shaman_master в списке точка ru

3 года назад

Примечание: эта документация неполная, ReflectionObject::export($exception):
Объект класса [  class Exception реализует Throwable ] {
  - Properties [7] {
    Property [  protected $message ]
    Property [  private $ строка ]
    Свойство [  защищенный $ код ]
    Свойство [  защищенный $ файл ]
    Свойство [  защищенная $ строка ]
    Свойство [  частный $ след ]
    Свойство [  частный $ предыдущий ]
  }
  – Методы [11] {
    Метод [  final private method __clone ] {
    }

    Метод [  public method __construct ] {

       – Параметры [3] {
       Параметр #0 [  $message ]
        Параметр #1 [  $ code ]
        Parameter #2 [  $previous ]
      }
    }

    Method [  public method __wakeup ] {
    }

    Method [  final public method getMessage ] {
    }

    Метод [конечный общедоступный метод getCode ] {
    }

  Метод [конечный общедоступный метод getFile ] {
   }

    Метод [конечный общедоступный метод getLine ] {
   }

    Метод [конечный общедоступный метод getTrace ] { 902 03     }

    Method [ final public method getPrevious ] {
    }

    Метод [final public method getTraceAsString ] {
    }

    Method [  public method __toString ] {
    }
  }
}
?>

Пропущено:

    Свойство [  private $string ]
    Property [  private $trace ]
    Property [  private $previous ]

    Method [  public method __wakeup ] {
    }

добавить примечание

Исключения или ошибки | Инструменты PHP для документации Visual Studio

PHP сообщает об ошибках, предупреждениях и уведомлениях, когда программа оказывается в неожиданном состоянии. Начиная с PHP7, это сообщение об ошибке в основном передается путем создания исключения.

Инструменты PHP для отладчика Visual Studio поддерживают оба типа обработки ошибок — традиционные ошибки PHP и исключения PHP.

Перерыв при возникновении исключения

Вы можете указать отладчику прерывать работу при возникновении исключения, что позволит вам проверить текущее состояние программы.

При открытом проекте PHP используйте Отладка | Окна | Настройки исключений , чтобы открыть окно Настройки исключений . Найти исключений PHP и убедитесь, что исключение, которое вы хотите прервать, отмечено флажком. Если исключение не указано в настройках исключений, отметьте пункт или вы можете проверить всю категорию Исключения PHP** .

В окне Настройки исключений вы также можете найти Ошибка , Предупреждение , Уведомление , которые являются не исключениями, а традиционными ошибками PHP. Они не разбиты на конкретные ошибки. Но вы можете включить/отключить их как целую категорию.

Затем, когда вы отлаживаете программу PHP, Visual Studio прервется при возникновении исключения так же, как если бы в этом месте присутствовала точка останова.

В диалоговом окне обработчика исключения будет представлена ​​информация об исключении, например тип исключения и сообщение. Вы можете проверить программу, оценить выражения, проверить стек вызовов и т. д.

Примечание: вы можете снять отметку Прервать при возникновении этого типа исключения прямо в обработчике исключений и продолжить отладку (нажмите F5 ). Visual Studio добавит этот тип исключения в настройки исключения и запомнит, что это исключение больше не должно прерываться.

Добавить или удалить исключение в настройках исключений

Настройки исключений перечисляют лишь несколько распространенных типов исключений. Скорее всего, вы не найдете в списке конкретное исключение, на котором хотите остановиться. Вы можете либо проверить или выберите исключение, которое вы хотите отключить.

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

Если вы хотите заблаговременно добавить (или удалить) исключение, в окне Настройки исключений выберите категорию Исключения PHP и нажмите кнопку «Добавить» (или кнопку «Удалить»).

Введите полное имя исключения (включая пространства имен). Убедитесь, что имя указано правильно, отладчик не проверяет, правильно ли вы написали тип исключения.

Необработанные исключения и фатальные ошибки

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