PHP: исключения против ошибок?
может быть, я пропустил его где-то в руководстве PHP, но в чем именно разница между ошибкой и исключением? Единственное различие, которое я вижу, заключается в том, что ошибки и исключения обрабатываются по-разному. Но что вызывает исключение и что вызывает ошибку?
10 ответов:
исключения брошенный - Они предназначены, чтобы быть пойманным. Ошибки, как правило, не подлежат восстановлению. Допустим, например, у вас есть блок кода, который будет вставить строку в базу данных. Возможно, что этот вызов завершится неудачей (дубликат ID) - вы захотите иметь "ошибку", которая в этом случае является "исключением". Когда вы вставляете эти строки, вы можете сделать что-то подобное
try { $row->insert(); $inserted = true; } catch (Exception $e) { echo "There was an error inserting the row - ".$e->getMessage(); $inserted = false; } echo "Some more stuff";выполнение программы будет продолжено-потому что вы "поймали" исключение. Исключение будет рассматриваться как ошибка, если оно не будет поймано. Это позволит вам продолжить выполнение программы после ее сбоя, а также.
Я обычно
set_error_handlerк функции, которая принимает ошибку и выдает исключение, так что все, что происходит, я просто буду иметь исключения для решения. Нет больше@file_get_contentsпросто хороший и аккуратный попробовать / поймать.в ситуациях отладки у меня также есть обработчик исключений, который выводит asp.net как Пейдж. Я публикую это на дороге, но если потребуется, я опубликую пример источника позже.
edit:
дополнение как и было обещано, я вырезал и вставил некоторые из моего кода вместе, чтобы сделать образец. Я сохранил ниже в файл на моей рабочей станции,вы можете БОЛЬШЕ НЕ посмотреть здесь (потому что связь разрывается).
<?php define( 'DEBUG', true ); class ErrorOrWarningException extends Exception { protected $_Context = null; public function getContext() { return $this->_Context; } public function setContext( $value ) { $this->_Context = $value; } public function __construct( $code, $message, $file, $line, $context ) { parent::__construct( $message, $code ); $this->file = $file; $this->line = $line; $this->setContext( $context ); } } /** * Inspire to write perfect code. everything is an exception, even minor warnings. **/ function error_to_exception( $code, $message, $file, $line, $context ) { throw new ErrorOrWarningException( $code, $message, $file, $line, $context ); } set_error_handler( 'error_to_exception' ); function global_exception_handler( $ex ) { ob_start(); dump_exception( $ex ); $dump = ob_get_clean(); // send email of dump to administrator?... // if we are in debug mode we are allowed to dump exceptions to the browser. if ( defined( 'DEBUG' ) && DEBUG == true ) { echo $dump; } else // if we are in production we give our visitor a nice message without all the details. { echo file_get_contents( 'static/errors/fatalexception.html' ); } exit; } function dump_exception( Exception $ex ) { $file = $ex->getFile(); $line = $ex->getLine(); if ( file_exists( $file ) ) { $lines = file( $file ); } ?><html> <head> <title><?= $ex->getMessage(); ?></title> <style type="text/css"> body { width : 800px; margin : auto; } ul.code { border : inset 1px; } ul.code li { white-space: pre ; list-style-type : none; font-family : monospace; } ul.code li.line { color : red; } table.trace { width : 100%; border-collapse : collapse; border : solid 1px black; } table.thead tr { background : rgb(240,240,240); } table.trace tr.odd { background : white; } table.trace tr.even { background : rgb(250,250,250); } table.trace td { padding : 2px 4px 2px 4px; } </style> </head> <body> <h1>Uncaught <?= get_class( $ex ); ?></h1> <h2><?= $ex->getMessage(); ?></h2> <p> An uncaught <?= get_class( $ex ); ?> was thrown on line <?= $line; ?> of file <?= basename( $file ); ?> that prevented further execution of this request. </p> <h2>Where it happened:</h2> <? if ( isset($lines) ) : ?> <code><?= $file; ?></code> <ul class="code"> <? for( $i = $line - 3; $i < $line + 3; $i ++ ) : ?> <? if ( $i > 0 && $i < count( $lines ) ) : ?> <? if ( $i == $line-1 ) : ?> <li class="line"><?= str_replace( "\n", "", $lines[$i] ); ?></li> <? else : ?> <li><?= str_replace( "\n", "", $lines[$i] ); ?></li> <? endif; ?> <? endif; ?> <? endfor; ?> </ul> <? endif; ?> <? if ( is_array( $ex->getTrace() ) ) : ?> <h2>Stack trace:</h2> <table class="trace"> <thead> <tr> <td>File</td> <td>Line</td> <td>Class</td> <td>Function</td> <td>Arguments</td> </tr> </thead> <tbody> <? foreach ( $ex->getTrace() as $i => $trace ) : ?> <tr class="<?= $i % 2 == 0 ? 'even' : 'odd'; ?>"> <td><?= isset($trace[ 'file' ]) ? basename($trace[ 'file' ]) : ''; ?></td> <td><?= isset($trace[ 'line' ]) ? $trace[ 'line' ] : ''; ?></td> <td><?= isset($trace[ 'class' ]) ? $trace[ 'class' ] : ''; ?></td> <td><?= isset($trace[ 'function' ]) ? $trace[ 'function' ] : ''; ?></td> <td> <? if( isset($trace[ 'args' ]) ) : ?> <? foreach ( $trace[ 'args' ] as $i => $arg ) : ?> <span title="<?= var_export( $arg, true ); ?>"><?= gettype( $arg ); ?></span> <?= $i < count( $trace['args'] ) -1 ? ',' : ''; ?> <? endforeach; ?> <? else : ?> NULL <? endif; ?> </td> </tr> <? endforeach;?> </tbody> </table> <? else : ?> <pre><?= $ex->getTraceAsString(); ?></pre> <? endif; ?> </body> </html><? // back in php } set_exception_handler( 'global_exception_handler' ); class X { function __construct() { trigger_error( 'Whoops!', E_USER_NOTICE ); } } $x = new X(); throw new Exception( 'Execution will never get here' ); ?>
ответ заслуживает разговора о слоне в комнате
ошибки-это старый способ обработки ошибки во время выполнения. Обычно код будет вызывать что-то вроде
set_error_handlerперед выполнением кода. Следуя традиции языка ассемблера прерывается. Вот как будет выглядеть некоторый базовый код.on error :divide_error print 1/0 print "this won't print" :divide_error if errcode = X print "divide by zero error"было трудно убедиться, что
set_error_handlerбудет вызван с правильным значением. И что еще хуже, может быть сделан звонок к отдельной процедуре, которая изменит обработчик ошибок. Плюс много раз звонки перемежались сset_error_handlerвызовы и обработчики. Коду было легко быстро выйти из-под контроля. Обработка исключений пришла на помощь путем формализации синтаксиса и семантики того, что действительно делал хороший код.try { print 1/0; print "this won't print"; } catch (DivideByZeroException $e) { print "divide by zero error"; }нет отдельной функции или риска вызова неправильного обработчика ошибок. Код теперь гарантированно будет в том же месте. Кроме того, мы получаем лучшие сообщения об ошибках.
PHP используется только для обработки ошибок, когда многие другие языки уже эволюционировали до предпочтительной модели обработки исключений. В конечном итоге создатели PHP реализовали обработку исключений. Но, вероятно, чтобы поддерживать старый код, они продолжали обрабатывать ошибки и предоставляли способ сделать обработку ошибок похожей на обработку исключений. Кроме того, нет никакой гарантии, что какой-то код не может сбросить обработчик ошибок, который был именно тем, что обработка исключений должна была обеспечить.
финал ответ
ошибки, которые были закодированы до того, как была реализована обработка исключений, скорее всего, все еще являются ошибками. Новые ошибки, скорее всего, исключения. Но нет никакого дизайна или логики, к которым относятся ошибки и которые являются исключениями. Он просто основан на том, что было доступно в то время, когда он был закодирован, и предпочтение программиста, кодирующего его.
одна вещь, чтобы добавить здесь об обработке исключений и ошибок. Для целей разработчика приложений ошибки и исключения - это "плохие вещи", которые вы хотите записать, чтобы узнать о проблемах, которые есть в вашем приложении, чтобы ваши клиенты имели лучший опыт в долгосрочной перспективе.
поэтому имеет смысл написать обработчик ошибок, который делает то же самое, что и для исключений.
как указано в других ответах, установка обработчика ошибок в exception thrower является лучшим способом обработки ошибок в PHP. Я использую немного более простую настройку:
set_error_handler(function ($errno, $errstr, $errfile, $errline ) { if (error_reporting()) { throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); } });обратите внимание:
error_reporting()проверяем, чтобы сохранить@оператора. Кроме того, нет необходимости определять пользовательское исключение, PHP имеет один хороший класс для этого.большим преимуществом исключения является то, что исключение имеет трассировку стека, связанную с ними, поэтому легко найти, где проблема.
Re: "но в чем именно разница между ошибкой и исключением?"
есть много хороших ответов здесь различия. Я просто добавлю кое - что, о чем еще не говорили-производительность. В частности, это касается разницы между швыряниями/обработка исключений и обрабатывать код возврата (успех или ошибка). Как правило, в PHP, это означает возвращение
falseилиnull, но они могут быть более подробными, например, с загрузка файла:http://php.net/manual/en/features.file-upload.errors.php вы даже можете вернуть объект исключения!Я сделал несколько запусков производительности на разных языках/системах. Вообще говоря, обработка исключений примерно в 10 000 раз медленнее, чем проверка кода возврата ошибки.
Итак, если он абсолютно, положительно должен закончить выполнение до того, как он даже начал - Ну, вам не повезло, потому что путешествия во времени не существует. Без времени путешествия, коды возврата-это самый быстрый вариант.
Edit:
PHP очень оптимизирован для обработки исключений. Тесты реального мира показывают, что выбрасывание исключения только в 2-10 раз медленнее, чем возврат значения.
Я думаю, что ответ, который вы ищете является то, что;
ошибки-это стандартные вещи, к которым вы привыкли, например, Эхо переменной$, которая не существует.
Исключения только из PHP 5 и далее и приходят при работе с объектами.чтобы все было просто:
исключения ошибки вы получаете при работе с объектами. Оператор try/catch позволяет вам что-то делать с ними, хотя и используется так же, как оператор if/else. Попробуйте это сделать, если проблема, не имеет значения, сделайте это.
Если вы не" ловите " исключение, то оно превращается в стандартную ошибку.
ошибки, ошибки фундаментальная PHP, которая, как правило, остановить свой сценарий.
Try / catch часто используется для установления соединений с базой данных, таких как PDO, что прекрасно, если вы хотите перенаправить скрипт или сделать что-то еще, если соединение не работает. Но если вы просто хотите отобразить сообщение об ошибке и остановить скрипт, то вам это не нужно, неперехваченное исключение превращается в фатальную ошибку. Также можно использовать параметр обработки ошибок на уровне всего сайта.
надеюсь, что это поможет
исключения выбрасываются намеренно кодом с помощью броска, ошибки... не столько.
ошибки возникают в результате чего-то, что обычно не обрабатывается. (Ошибки ввода-вывода, ошибки TCP / IP, ошибки нулевой ссылки)
Я намерен дать вам самое необычное обсуждение контроля над ошибками.
Я построил очень хороший обработчик ошибок в язык несколько лет назад, и хотя некоторые из имен изменились, принципы обработки ошибок сегодня те же. У меня была специально построенная многозадачная ОС и должна была быть возможность восстанавливаться от ошибок данных на всех уровнях без утечек памяти, роста стека или сбоев. Далее следует мое понимание того, как должны работать ошибки и исключения и как они отличаются. Я просто скажу, что у меня нет понимания того, как работает внутренняя часть try catch, поэтому я предполагаю в какой-то мере.
первое, что происходит под крышками для обработки ошибок, - это переход из одного состояния программы в другое. Как это делается? Я дойду до этого.
исторически ошибки старше и проще, а исключения новее и немного сложнее и способны. Ошибки работают нормально, пока вам не нужно их пузырить, что эквивалентно передаче сложная проблема для вашего руководителя.
ошибки могут быть числами, такими как номера ошибок, а иногда и с одной или несколькими связанными строками. Например, если возникает ошибка чтения файла, вы можете сообщить, что это такое, и, возможно, изящно потерпеть неудачу. (Хэй, это шаг вверх от просто рушится, как в старые времена.)
что не часто говорят об исключениях, так это то, что исключения-это объекты, расположенные в специальном стеке исключений. Это похоже на стек возврата для потока программы, но он держит вернет государство только пробует ошибку и ловит. (Я привык называть их ePush и ePop, а ?Аборт был условным броском, который бы ePop и восстановился до этого уровня, в то время как аборт был полным умиранием или выходом.)
в нижней части стека находится информация о начальном вызывающем объекте, который знает о состоянии, когда была запущена внешняя попытка, что часто происходит при запуске вашей программы. На вершине этого или следующего слоя в стеке, с тем, чтобы быть детьми, и вниз будучи родителями, является объектом исключения следующего внутреннего блока try/catch.
Если вы кладете попытку внутри попытки, вы укладываете внутреннюю попытку поверх внешней попытки. Когда во внутренней попытке возникает ошибка и либо внутренний улов не может ее обработать, либо ошибка выбрасывается во внешнюю попытку, то управление передается внешнему блоку catch (объекту), чтобы увидеть, может ли он обрабатывать ошибку, т. е. ваш супервизор.
Так что этот стек ошибок действительно делает, чтобы иметь возможность отмечать и восстановление потока программы и состояния системы, другими словами, это позволяет программе не сбой стека возврата и испортить вещи для других (данные), когда все идет не так. Таким образом, он также сохраняет состояние любых других ресурсов, таких как пулы выделения памяти, и поэтому он может очистить их, когда catch будет выполнен. В целом это может быть очень сложная вещь, и именно поэтому обработка исключений часто медленно. В общем, довольно много государства должно войти в эти блоки исключений.
Так что попробовать/поймать блок вроде устанавливает состояние, в которое можно вернуться, если все остальное будет испорчено. Это как родитель. Когда наши жизни будут испорчены, мы можем снова упасть на колени наших родителей, и они снова все исправят.
надеюсь, я вас не разочаровал.
Как только set_error_handler() определяется, ошибки обработчика похож на исключения. Смотрите код ниже:
<?php function handleErrors( $e_code ) { echo "error code: " . $e_code . "<br>"; } set_error_handler( "handleErrors" ); trigger_error( "trigger a fatal error", E_USER_ERROR); echo "after error."; //it would run if set_error_handler is defined, otherwise, it wouldn't show ?>
Comments