Я видел множество обучающих программ, в которых демонстрационная простая попытка улавливает, скажем, действие открытия файла. Но я никогда не видел большого, "настоящего" примера. Может ли кто-нибудь предоставить мне несколько случаев, когда они имеют или будут использовать исключения? И действительно ли необходимо расширять класс исключений только для того, чтобы выбросить исключение? И, наконец, при бросании исключений, вызывает ли script exit();? Или он регистрирует его и продолжает выполнение script?
Когда следует использовать исключения PHP?
Ответ 1
Мы используем исключения в наших проектах.
Один конкретный экземпляр предназначен для действий, требующих входа пользователя в систему или при регистрации. Мы используем Исключения для управления потоком при ошибках. Если текущий пользователь не зарегистрирован, мы генерируем исключение. Обработчик исключений затем перенаправляет их на страницу loggin.
Используя наше действие регистрации в качестве примера, мы расширяем исключение следующим образом:
class RegistrationFailed extends Exception {}
Теперь в нашем операторе catch
внутри регистрационного кода мы можем протестировать исключение RegistrationFailed и обработать его соответствующим образом. В противном случае, когда исключение не является регистрационным, мы разрешаем ему пузыриться, потому что нас это не интересует.
try {
// do registration here
}
catch(RegistrationFailed $e) {
// handle the failed registration
}
catch(SomeOtherException $e) {
// handle other errors like this...
}
// All other errors will not be caught and will bubble up
Другой пример - внутри наших классов-оболочек, которые разработчики должны расширять. Мы используем Reflection для обеспечения того, чтобы дочерние классы правильно реализовали свои методы и обеспечили правильный интерфейс. Если мы не уведомим разработчика этого класса через Exceptions, позволяющие им знать, какой-либо конкретный интерфейс или метод должен быть предоставлен дочерним классом.
Изменить: Я уже слышу комментарии о том, что "вы не должны использовать обработку ошибок для управления потоком!" однако для проекта, обсуждавшегося выше, это было необходимо.
В нормальном потоке программы ожидается неудачная регистрация из-за многих правил проверки, которые могут завершиться неудачно, например, слишком короткий пароль.
Однако, это приложение ajax, поэтому возможно, что кто-то может попытаться получить доступ к URL-адресу ajax вручную, когда они не вошли в систему. Это исключение, и поэтому мы обрабатываем его как таковое.
Ответ 2
Исключения предназначены для обработки ошибок (по крайней мере, в PHP). Предположим, что вы находитесь в рутине, и возникает ошибка, которую вы не можете обработать в текущем контексте.
Пример:
<?php
/**
* @throws Exception_NoFile
*/
function read_file($file) {
if(!file_exists($file)) {
throw new Exception_NoFile($file);
}
/* ... nominal case */
}
В этой ситуации вы не можете продолжить номинальный случай, потому что нет файла для обработки. Вы должны выбрать:
-
return с недопустимым значением возврата (это практика C, например: return -1 или использование флагов состояния)
-
выбросьте исключение и надейтесь, что кто-то поймает его выше. Если ваш код клиента исключает его, без проблем, он может попробовать другой путь или перестроить исключение. Если ваш клиент не готов обрабатывать те ситуации, когда запрошенный файл не существует... ваш код завершится с отсутствием исключения, как это было бы при чтении несуществующего файла в другом подходе.
Ответ 3
Вы должны проверить структуру symfony - они действительно используют много Исключений.
Они используют Исключения для ошибок конфигурации, говорят, что вы забыли поместить файл, в котором контроллер ожидает его найти, - это будет исключение, потому что в нем нет ничего, что могло бы сделать с ним.
Они используют Exception для неизвестных ошибок: сбой базы данных по какой-то странной причине, там ничего не может сделать с ней, поэтому он генерирует исключение
И у них разные обработчики Exception для разных сред. Когда исключение происходит в режиме "devel", вы получаете хорошую страницу со стеком и объяснением, когда вы находитесь в режиме "производства", вы перенаправляетесь на пользовательскую страницу 500.
Ответ 4
Обработка исключений сложна. Это требует тщательного рассмотрения проекта и способа устранения ошибок. Вы должны попытаться определить свои рекомендации об исключениях на раннем этапе своего проекта и придерживаться его.
Я написал общий Рекомендации об исключениях, которые я придумал после обширных исследований предмета. Большинство этих рекомендаций могут использоваться для всех проектов на любом языке, который поддерживает исключения. Некоторые из рекомендаций будут специфичными для Java. В конце вы должны иметь надежный набор рекомендаций, которые помогут вам справиться с исключениями и условиями ошибки.
Вот несколько моментов для рассмотрения
Не подвергайте внутренние, специфичные для реализации детали своим клиентам
Избегайте подвергать внутренние исключения конкретной реализации вашим клиентам, особенно тем, которые содержатся в сторонней библиотеке. Это общее объектно-ориентированное эмпирическое правило и его значение для вашего иерархического дизайна исключений. У вас нет контроля над сторонней библиотекой, которая может изменить свои подписки на исключения и разорвать все ваши контракты API с вашими клиентами. Вместо этого оберните те исключения третьих лиц (например, SQLException) в свои собственные пользовательские исключения. Таким образом, вы будете иметь гораздо большую гибкость, чтобы изменить стороннюю библиотеку в будущем, не нарушая контракт с клиентом API.
Создайте собственную иерархию исключений для сложных проектов
Вообще говоря, создайте свою собственную иерархию исключений для более сложных модулей, особенно если вы имеете дело с конкретными исключениями для реализации в сторонних библиотеках. Каждый из ваших пакетов/модулей может иметь свои собственные исключения общего уровня. Для Java должен быть определен хотя бы один, который наследуется от RuntimeException. Оберните все исключения для реализации в своих пользовательских исключениях, чтобы ваши клиенты зависели только от ваших пользовательских исключений и/или общих исключений Java. Это даст вам большую гибкость для реорганизации конкретного кода реализации позже, не нарушая контракты API.
Если требуется более мелкая обработка ошибок, вы можете дополнительно подклассифицировать свои пользовательские исключения для обработки конкретных случаев и разрешить восстановление ошибок. Например, если вы подключаетесь к базе данных SQL, вы можете вызывать исключение ConnectionTimeoutException таким образом, чтобы при необходимости клиент мог повторить соединение N раз перед сдачей. Таким образом, вы можете позже изменить свой движок базы данных на NoSQL и по-прежнему разрешить пересоединения, а клиентский код останется прежним.
Документировать все исключения
Внимательно документируйте все исключения, которые ваш пакет/модуль/приложение выбрасывает в определении javadoc для каждого публичного метода. Несоблюдение этого требования может помешать вашим пользователям API и заставить их не доверять вашим документам API. Вы действительно не хотите, чтобы ваши клиенты копались в вашем источнике, чтобы узнать, что вы выбрасываете конкретное исключение, не так ли?
Выбросьте исключения как можно раньше.
Проверяйте все входы на общедоступные API-методы и выдавайте исключение, как только вы обнаружите несоответствия между вашими ожидаемыми параметрами и тем, что было предоставлено. Чем раньше вы генерируете исключение, тем меньше вероятность повреждения данных, потому что плохие данные не попадают в более глубокие части вашего кода. Он также дает ценную обратную связь вашим клиентам своевременно, а не глубоко в вашем коде, где что-то бросает неясное исключение с плохим сообщением, таким как "Внутренняя ошибка или исключение NullPointerException".
Правильно регистрировать исключения
Следуйте рекомендациям вашей структуры ведения журнала, чтобы правильно регистрировать исключения с их трассировкой сообщения и стека. Вы не хотите потерять или
Ответ 5
Я чувствую, что многие люди путают "неудачи" и "исключения" как одно и то же. Слово "ошибка" может относиться к одному, но я использую его для отказа.
Отказ - когда операция не удалась
Исключение - когда возникает неожиданное или из нормального состояния потока
Например, если робот пытается добраться до места назначения и пропускает отметку - этот сбой. Но если он ломает ногу или крышу падает на нее, это исключение.
Если крыша падает, я исключаю, что крыша упала.
Если робот пропускает отметку, я не бросаю исключение, я возвращаю ложь или возвращаю сообщение об ошибке, подобное "Не удалось добраться до места назначения, потому что крыша упала".
try {
Walk to the cabinet;
}
catch (RoofFell_Exception $e) {
return "Could not reach the destination because the roof fell.";
}
catch (Legbroke_Exception $e) {
return "Could not reach the destination because a leg broke.";
}
if($current_location == 'cabinet') {
return "Destination reached";
}
return false;
Ответ 6
Исключения - это просто способ переместить крайние случаи или ошибки (которые на самом деле являются просто большими событиями в крайнем случае) из большей части кода, чтобы помешать им сделать 99% основного потока кода, загроможденного множеством переключателей/МФС.
Вы можете рассматривать их как своего рода оператор обратного переключения, где события внутри try {} определяют, какой, если таковой имеется, блок catch также происходит.
Это означает, что вам никогда не придется использовать их, если они вам не нравятся. Но они могут облегчить чтение кода.
Ответ 7
Отличное место для использования обработки исключений - это когда ваша программа пытается подключиться или получать доступ к I/O (файлы, базы данных, сети, устройства).
-
Используйте обработку исключений, когда блок кода вызова (функция/метод) пытается получить доступ к файлу.
-
Используйте обработку исключений, когда блок вызова кода (функция/метод) пытается подключиться к базе данных.
-
Используйте обработку исключений, когда блок кода вызова (функция/метод) пытается запустить запрос в базе данных (любая попытка доступа к таблицам/представлениям базы данных и тому подобное).
-
Вы можете сказать то же самое о сетевом соединении или доступе.
Для доступа к памяти требуется ввод-вывод (который включает в себя хранение вещей в файлах $_SESSION), но большинство новичков не помещают всю свою программу в пределах структуры try...catch
. Хороший пример использования исключений и расширения класса Exception можно найти в книге Мэтта Дойля "Начало PHP 5.3", гл. 20, p. 652-60.
Я мог бы также сказать, что обучение сочетанию использования обработки исключений с set_error_handler()
, trigger_error()
, error_log()
внутри блока catch
может позволить вам сохранять настраиваемые, дружественные к разработчикам сообщения об ошибках, которые могут возникнуть у вас эхо отзывалось на ваше устройство вывода (browser/stdout) в процессе разработки. То есть в процессе производства ваш php.ini будет иметь display_errors
off и log_errors
будет включен. Если вы, возможно, повторили что-то вроде "К сожалению, я не могу подключиться к базе данных учета", когда соединение с указанной базой данных завершилось неудачей, просто отправьте ту же строку текста в error_log()
, и ваши личные сообщения об ошибках все равно могут быть зарегистрированы.
Пример:
function custom_handler($arg1, $arg2, $arg3, $arg4, $arg5)
{
...
...
error_log(blah, blah, blah)
}
set_error_handler('custom_handler'); <--takes over this duty from PHP
$error = NULL;
try
{
if(!connect_to_mythical_database('accounting'))
{
$error = 'I cannot connect to the accounting database';
throw new Exception(supply-correct-arguments);
}
}
catch (Exception $e)
{
trigger_error(supply-correct-arguments); <-- does what 'custom_handler' instructs.
error_log($error, blah, blah); <---Your friendly message here
header('Location: http://www.myhomepage.com');
exit;
}
Примечание. Внутри custom_handler()
вы можете использовать error_log()
для регистрации сообщений об ошибках PHP в файле, отправки их по электронной почте или обоих журналов и отправки стандартных сообщений об ошибках PHP. Таким образом, trigger_error()
управляется PHP (по умолчанию) или вашим "custom_handler", который может реализовать блок error_log()', all of which can be activated by the
catch` вашего обработчика исключений.