php ошибки и исключения

Исключения в PHP. Правильное применение исключений

Содержание:

php ошибки и исключения. Смотреть фото php ошибки и исключения. Смотреть картинку php ошибки и исключения. Картинка про php ошибки и исключения. Фото php ошибки и исключения

Если ты изучаешь ООП, то наверняка натыкался на понятие исключения, а может даже уже видел его где-то в коде. В этом уроке я постараюсь объяснить, что такое исключение в PHP7 и зачем они нужны. Расскажу когда, какое и как правильно применять то или иное исключение при разработке.

Что такое исключение в PHP7

Пример: Предположим, мы разрабатываем блог и работаем над методами удаления категории. По логике вещей нельзя удалить категорию, в которой есть посты. Здесь нам приходят на помощь исключения. Очень урезанный и простой пример, но отражающий суть:

Класс Exception

Генерация исключений

Обработка исключений

Ловим исключение в блоке try :

Создание подклассов класса Exception

Пример собственного класса исключения:

Полная иерархия исключений в PHP7

Throwable

Throwable — это даже не исключение, а интерфейс, который реализуют все остальные рассматриваемые классы. Добавлен в PHP7.

Exception

LogicException

Используется, когда ваш код возвращает значение, которое не должен возвращать. Часто вызывается при разных багах в коде. Потомки этого класса используются в более специализированных ситуациях. Если ни одна из них не подходит под ваш случай, можно использовать LogicException.

BadFunctionCallException

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

BadMethodCallException

Пример использования этих двух исключений:

DomainException

Если в коде подразумеваются некие ограничения для значений, то это исключение можно вызывать, когда значение выходит за эти ограничения. Например, у вас дни недели обозначаются числами от 1 до 7, а ваш метод получает внезапно на вход 0 или 9, или, скажем, вы ожидаете число, обозначающее количество зрителей в зале, а получаете отрицательное значени. В таких случаях и вызывается DomainException. Также можно использовать для разных проверок параметров, когда параметры нужных типов, но при этом не проходят проверку на значение. Например:

InvalidArgumentException

Вызываем, когда ожидаемые аргументы в функции/методе некорректно сформированы. Например, ожидается целое число, а на входе строка или ожидается GET, а пришел POST и т.п.

LengthException

Вызываем, если длина чего-то слишком велика или мала. Например, имя файла слишком короткое или длина строки слишком большая.

RuntimeException

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

OutOfBoundsException

Пример использования в реализации ArrayAccess :

OutOfRangeException

OverflowException

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

UnderflowException

Обратная OverflowException ситуация, когда, например, класс-контейнер имеет недостаточно элементов для осуществления операции. Например, когда он пуст, а вы пытаетесь удалить элемент.

RangeException

UnexpectedValueException

Используется, когда значение выходит из ряда ожидаемых значений. Часто применяется, когда то, что вернулось из вызываемой функции, не соответствует тому, что мы от нее ожидаем в ответе по типу или значению. Сюда не относятся арифметические ошибки или ошибки, связанные с буфером.

Вот пример, когда у нас есть список констант, и функция getValueOfX должна гарантированно возвращать значение одной из них.

Error

AssertionError

ParseError

Для ошибок парсинга, когда подключаемый по include/require код вызывает ошибку синтаксиса, ошибок функции eval() и т.п.

TypeError

Учебный пример, в котором есть примеры использования всех классов исключений:

Вот и всё. Думаю, материал буде полезен как новичкам, так и более продвинутым программистам. Я постарался систематизировать информацию об исключениях в одной статье.

Источник

Throwable exception и ошибки в php7

Обратите внимание, что другие виды ошибок, такие как warinng и notice остаются без изменения в php 7.

Throwable

Оба класса, и Error и Exception реализуют новый интерфейс Throwable.
Новая иерархия исключения состоит в следующем:

Если Throwable определить в коде PHP 7, то выглядит это так:

Этот интерфейс должен быть знаком. Методы Throwable практически идентичны методам Exception. Разница лишь в том, что Throwable::getPrevious() может вернуть любой экземпляр Throwable, а не просто Exception. Конструкторы Exception и Error принимают любой экземпляр Throwable как предыдущее исключение.
Throwable может быть использован в блоке try/catch для отлова и Exception и Error (и любых других возможных в будущем исключений). Помните, что хорошей практикой является «ловля» исключений определенным классом исключений и обработка каждого типа отдельно. Но и иногда требуется отлавливать любое исключение. В PHP 7 try/catch блок для всех исключений должен использовать Throwable вместо Exception.

Пользовательские классы не могут реализовывать Throwable. Это было сделано для предсказуемости: только экземпляры Exception или Error могут быть брошены. Кроме того, исключения содержат информацию о том, где объект был создан в stack trace. В пользовательских классах нет необходимых параметров, для хранения этой информации.

Error

Практически все ошибки (E_ERROR, E_RECOVERABLE_ERROR) в PHP 5.x, в PHP 7 выбрасывается экземпляром Error. Как и любые другие исключения, Error может быть пойман используя try/catch блок.

Большинство ошибок, которые были «фатальны» в PHP 5.x в PHP 7 буду выбрасывать простые Error объекты, но некоторые будут выбрасывать объекты подклассов: TypeError, ParseError и AssertionError.

TypeError

Экземпляр TypeError выбрасывается, когда аргументы метода или возвращаемое значение не совпадает с объявленным типом.

ParseError

ParseError выбрасывается, когда подключаемый (путем include/require) файл или код в eval содержит ошибки синтаксиса.

AssertionError

Когда условие, заданное методом assert() не выполняется, выбрасывается AssertionError:

Метод assert() выполняется и выбрасывается AssertionError только, если они включены в настройках: zend.assertions = 1 и assert.exception = 1.

Использование Error в своём коде

Мы можем использовать класс Error, а также расширить Error, создав собственную иерархию класса Error. Это порождает вопрос: какие исключение должен выбрасывать Exception, а какие Error?
Error должен использоваться для указания проблем в коде, требующих внимания программиста (такие как неправильный тип входящих данных и синтаксические ошибки). Exception должен использоваться, когда исключение может «безопасно» обработаться, и выполнение программы может продолжиться.
Поскольку, объекты Error не могут быть обработаны во время выполнения программы, «ловля» Error должна быть редкостью. В целом, Error должны быть пойманы только для логирования их, необходимой «чистки данных», и отображения ошибки для пользователя.

Источник

Обработка ошибочных ситуаций в PHP

«Если человек может сделать ошибку, он ее сделает. Если же вы полагаете, что ошибку в данной ситуации совершить невозможно, то вы ошибаетесь».

В PHP все виды ошибок и предупреждений разбиты на несколько категорий:

КонстантаОписание
E_ALLВсе типы ошибок
E_ERRORФатальная ошибка на этапе исполнения
E_WARNINGПредупреждение на этапе исполнения (нефатальная ошибка)
E_PARSEОшибка синтаксиса
E_NOTICEЗамечание на этапе исполнения (менее серьезное, чем предупреждение)
E_CORE_ERRORФатальная ошибка на этапе инициализации PHP-машины
E_CORE_WARNINGПредупреждение на этапе инициализации PHP-машины (нефатальная ошибка)
E_COMPILE_ERRORФатальная ошибка на этапе компиляции
E_COMPILE_WARNINGПредупреждение на этапе компиляции (нефатальная ошибка)
E_USER_ERRORГенерируемое пользователем сообщение об ошибке
E_USER_WARNINGГенерируемое пользователем предупреждение
E_USER_NOTICEГенерируемое пользователем замечание

Стандартное значение режима генерации сообщений об ошибках равно E_ALL &

E_NOTICE, что соответствует выводу всех сообщений, не относящихся к категории E_NOTICE.

Функция настройки системного журнала error_reporting() устанавливает уровень выводимых соообщений об ошибках. Этой функции передаются константы, описанные выше.

Обработка исключений (exception)

Обработать возникающие исключения можно с помощью конструкции:

Методы исключений

PHP позволяет использовать свой обработчик исключений. Для этого необходимо объявить собственную функцию обработки и зарегистрировать её при помощи функции set_exception_handler().

После этого все возникающие исключения, не обрамлённые конструкцией try. catch, будут передаваться в объявленную вами функцию. Например, можно изменить функцию, чтобы она писала все исключения в файл и выдавала пользователю в браузер "красивое" сообщение об ошибке сервера:

Эта функция очень полезна в процессе отладки скриптов непосредственно на сервере.

Источник

Обработка исключений

Конструкция try catch finally

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

Программа выводит результат деления. Поскольку делитель равен 0, а на ноль делить нельзя, то при выполнении деления программа завершится, и в браузере мы увидим что-то типа следующего:

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

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

Для обработки исключений в PHP применяется конструкция try-catch :

Например, обработаем ошибку с делением на ноль:

В итоге при выполнении программа выведет следующее:

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

Типы ошибок и исключений

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

php ошибки и исключения. Смотреть фото php ошибки и исключения. Смотреть картинку php ошибки и исключения. Картинка про php ошибки и исключения. Фото php ошибки и исключения

Блок catch

Класс DivisionByZeroError унаследован от ArithmeticError, который, в свою очередь, унаследован от Error, реализующего интерфейс Throwable. Поэтому класс DivisionByZeroError представляет более конкретный тип и представляемые им ошибки должны обрабатываться в первую очередь. А тип Throwable представляет наиболее общий тип, так как ему соответствуют все возможные ошибки и исключения, поэтому блоки catch с таким типом должны идти в конце.

Если нам надо обрабатывать в принципе все ошибки и исключения, то мы можем определить только обработку общего для всех них типа Throwable:

Начиная с версии PHP 8.0 в блоке catch можно просто указать тип обрабатываемого исключения, не определяя переменную:

Получение информации об ошибках и исключениях

Интерфейс Throwable предоставляет ряд методов, которые позволяют получить некоторую информацию о возникшем исключении:

getMessage() : возвращает сообщение об ошибке

getCode() : возвращает код исключения

getFile() : возвращает название файла, в котором возникла ошибка

getLine() : возвращает номер строки, в которой возникла ошибка

getTrace() : возвращает трассировку стека

getTraceAsString() : возвращает трассировку стека в виде строки

Применим некоторые из этих методов:

Блок finally

Источник

Многие программисты почему-то считают, что исключения и ошибки — это одно и то же. Кто-то постоянно кидает exception, кто-то через errorHandler превращает ошибки в исключения. Некоторые пытаются увеличить производительность, используя исключения. Но, на самом деле, exception и ошибки — это совершенно разные механизмы. Не надо одним механизмом заменять другой. Они созданы для разных целей.

Когда появился php5 с исключениями, а затем ZendFramework, который всегда кидает исключения — я не мог понять: чем же exception лучше моего любимого trigger_error()? Долго думал, обсуждал с коллегами и разобрался в этом вопросе. Теперь я чётко знаю, где использовать trigger_error(), а где throw new Exception().

В чём же принципиальная разница между ними?

Ошибки

Ошибки — это то, что нельзя исправить, об этом можно только сообщить: записать в лог, отправить email разработчику и извинится перед пользователем. Например, если мой движок не может подключиться к БД, то это ошибка. Всё. Точка. Без БД сайт не работает, и я не могу с этим ничего сделать. Поэтому я вызываю ales_kaput() и trigger_error(), а мой errorHandler отправит мне email и покажет посетителю сообщение «Извините, сайт не работает».

Exception

Исключения — это не ошибки, это всего лишь особые ситуации, которые нужно как-то обработать. Например, если в калькуляторе вы попробуете разделить на ноль, то калькулятор не зависнет, не будет отсылать сообщения разработчику и извинятся перед вами. Такие ситуации можно обрабатывать обычным if-ом. Строго говоря, исключения — это конструкция языка позволяющая управлять потоком выполнения. Это конструкция, стоящая в одном ряду с if, for и return. И всё. Этот механизм ничем более не является. Только управление потоком.

Их основное предназначение: пробрасывать по каскаду. Покажу это на примере: есть три функции, которые вызывают друг друга каскадом:

Эту задачу можно было бы решить без механизма exception. Например, можно заставить все функции возвращать специальный тип (если ты матёрый пэхапэшник, то должен вспомнить PEAR_Error). Для простоты я обойдусь null-ом:

Задача выполнена, но, обратите внимание, мне пришлось модифицировать промежуточную функцию b(), чтобы она пробрасывала результат работы нижестоящей функции выше по каскаду. А если у меня каскад из 5 или 10 функций? То мне пришлось бы модифицировать ВСЕ промежуточные функции. А если исключительная ситуация в конструкторе? То мне пришлось бы подставлять костыли.

А теперь решение с использованием Exception:

Таким образом, получается, что ошибки и исключения — это совершенно разные инструменты для решения совершенно разных задач:
ошибка — не поправимая ситуация;
исключение – позволяет прервать выполнение каскада функций и пробросить некоторую информацию. Что-то вроде глобального оператора return. Если у Вас нет каскада, то вам достаточно использовать if или return.

Ошибки не всегда являются ошибками

Некоторые могут мне возразить: «Посмотри в Zend Framework — там всегда кидают исключения. Это best practics, и надо делать также. Даже если не удалось подключиться к БД, надо кидать исключение».

В этой статье я как раз хочу развеять это заблуждение. Zend действительно является best practics, но программисты Зенда находятся на другой лодке и делают другие вещи. Принципиальная разница между ними и мной в том, что они пишут универсальную библиотеку, которая будет использоваться во многих проектах. И они со своей колокольни не могут сказать, что является критической ошибкой, а что является поправимой.

Например, в вашем проекте может быть несколько MySQL серверов и вы можете переключаться между ними при падении одного из них. По этому, Zend_Db, как универсальная библиотека, кидает исключение, а что с ним делать — решайте сами. Exception это гибко — вы сами решаете на каком уровне и какой тип ситуаций ловить. Вы можете вывести сообщение об ошибке или попытаться исправить возникшую ситуацию, если знаете как. При написании универсальных библиотек необходимо всегда кидать исключения. Это делает библиотеку более гибкой.

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *