Исключения - это такая штука, что только в PHP является экзотикой, а в нормальный ООП языках - это одно из основных средств, так что изучать однозначно надо.
alex455 В каких ситуациях исключения лучше отображения ошибок самим PHP? только во время разработки, может быть. Вобще выводить ошибки пользователю - бессмысленное занятие
Да ладно. index.php: PHP: <?php try { /* весь код */ } catch { /* универсальный шаблон сообщения о ошибке, текст ошибки извлекаем из exception */ } грубо говоря, внутри одного try можно выполнять любой код, и где-бы не случился throw, пользователь увидит стандартное сообщение, ЕСЛИ этот exception не будет перехвачен раньше (некоторые ошибки надо не пользователю показывать, а обрабатывать как отказ операции). Это прекрасный механизм
Да вы что хоть, какое отображение ошибок... Исключения - отличный инструмент обработки ошибок внутри программы, скажем есть ф-я, которая да нет выдает, ей передается проксик, handler pdo или mysql (может не хендлек конечно, не помню точно), суть в том, что при ошибке с подключением к нету или ошибкой с базой, или еще какой то ошибкой выдавать исключение, которое и на наследнике реализовано быть может, а перехватывать и обрабатывать его можно в любом месте, где выполняется ф-я, был проект, где в доках к каждой ф-и был написан набор исключений, которые выдавать она может, при этом если ф-я выполняет другую, которая выдает искл-я, то она может их обрабатывать и в соответствии с этим либо продолжать выполняться, либо выдавать собственные исключения, либо пробрасывать выше пришедшие исключения... Вывод - исключения - замечательная вещь, весь вопрос где они критины, а где нет, в идеале, я думаю, они должны быть в каждом проекте, но это слишком трудоемко (например исключение если вдруг во время вып-я скрипта база перестала отвечать)... МБ немножк неграмотно написал, быстро писал прост
Re: Часто ли вы используете обработку ошибок (try, throw,cat Да, я часто использую try-catch. Да, это имеет смысл изучать. Обработка лучше отображения ошибок самим PHP практически во всех случаях. Собственно, такого выбора нет. Есть выбор между 1) обработкой исключений через try/catch, 2)подавлением сообщений об ошибках и обработкой полученного некорректного результата и 3) использованием set_exception_handler.
Механизму исключений в РНР ещё многому нужно научиться. Выглядит красиво, а по факту имеем: 1. Перехват фатальных ошибок с помощью register_shutdown_function 2. Перехват некритичных ошибок set_error_handler 3. Передача исключений из самой жопы с помощью set_exception_handler Вкупе с неправильной архитектурой останется только купить попкорн и наслаждаться. А так - сюрпризов будет куча. Не смог РНР обратиться к функции по религиозным причинам (будем расставлять везде function_exists ради throw?) - курим в сторонке. Никто нас эксепшнами не побалует.
Это не механизму PHP нужно многому научиться, а "программистам" повзрослеть. Функция у них делать куда-то, ага.
Ты работал когда-нибудь с кодом, который сам не писал? Тогда очень странно читать то, что ты пишешь =)
Какое отношение эксепшены имеют к коду, "который сам не писал"? У эксепшенов есть четкое назначение - передача вверх информации об фатальной ошибке бизнес-логики, а всякие "забытые" функции и прочее производящее фатальную ошибку исполнения php кода к эксепшенам отношения не имеет. Последние вообще обрабатывать на уровне своего приложения стоит только в одном случае - если нужно нарисовать полное сообщение об ошибке с трекингом стека вызовов. В реальном приложении ошибка php кода - это кривые руки, что не исправляется. А вот ошибка бизнес-логики, часто, может быть проанализирвана и проигнорирована выше.
Питона не знаю, поэтому ничего сказать не могу. Но если там действительно без исключений никуда, то это плохо. Плох тот язык, в котором постоянно приходится обрабатывать ошибки. Имхо, разумеется.
отследить, но что делать с этим результатом? одно дело где-то вначале выполнения написать PHP: <?php try { //blablabla } catch (Exception $e) { // красивое сообщение пользователю "Попробуйте снова через 5 секунд" с записью в лог "что-то не так" и сообщением админу } другое в каждой функции писать PHP: <?php if (0 != ($result = doSomething()) { return $result; } else { // blabla }
KMB вы бы как-нибудь аргументировали свою точку зрения, ссылки на статьи бы привели. А если это, вдруг, плод ваших мыслей, то тогда тем более ждём разгромной статьи на тему "правильно написанные программ", будет очень интересно просветиться.
try...catch - жутко удобная штука. Если правильно использовать. Для себя вижу следующие плюсы 1) Обработка ошибок сосредоточена в одном месте. 2) Дополнительная возможность управления ходом выполнения - разные типы исключений можно обрабатывать по-разному, и опять же - всё в одном месте.
Знал бы где упадешь - солому бы постелил try-catch это и есть солома, потому что заранее неизвестно ничего. А вдруг вытащат жесткий диск сис-админы во время копирования файла? И че тогда? =)) Вызовем функцию check_disk_ejected() ?
теперь всегда. core/loader.php PHP: <?php error_reporting ( E_ALL ); $sCoreDir = rtrim ( realpath ( dirname ( __FILE__ ) ), DIRECTORY_SEPARATOR ); date_default_timezone_set ( 'Europe/Moscow' ); require_once $sCoreDir . '/autoload.php'; require_once $sCoreDir . '/exception.php'; function WRXErrorHandler($errno, $errstr, $errfile, $errline) { switch ($errno) { case E_USER_ERROR : $sError = 'UERROR'; break; case E_USER_DEPRECATED : $sError = 'UDEPRECATED'; break; case E_USER_WARNING : $sError = 'UWARNING'; break; case E_USER_NOTICE : $sError = 'UNOTICE'; break; case E_NOTICE : $sError = 'ENOTICE'; break; case E_ERROR : $sError = 'EERROR'; break; case E_WARNING : $sError = 'EWARNING'; break; case E_PARSE : $sError = 'EPARSE'; break; case E_NOTICE : $sError = 'ENOTICE'; break; default : $sError = 'UNKNOWN'; break; } throw new WRXException ( "WRX $sError($errno): $errstr", 0, $errfile, $errline ); return false; } function WRXExceptionHandler(WRXException $Exception) { ob_end_clean(); print ('<pre>') ; print ("\nWRX Exception: [" . $Exception->getCode () . "] " . $Exception->getMessage ()) ; print ("\nWRX Exception: [" . $Exception->getFile () . "(" . $Exception->getLine ()) . ")]"; print ("\n") ; print ("\n" . $Exception->getTraceAsString ()) ; } function WRXFatalErrorHandler($buffer) { if (preg_match ( "/Fatal error: (.+)/", $buffer, $regs )) { return "<pre>WRX FATAL: " . $regs [1]; } return $buffer; } set_error_handler ( 'WRXErrorHandler', E_ALL ); set_exception_handler ( 'WRXExceptionHandler' ); ob_start ( "WRXFatalErrorHandler" ); WRXCore::getInstance (); core/exception.php PHP: <?php class WRXException extends Exception { public function __construct($sMessage, $iCode = 0, $sFile = '', $iLine = 0, $ePrev = null) { parent::__construct ( $sMessage, $iCode , $ePrev); $this->file = $sFile; $this->line = $iLine; } } core/autoload.php PHP: <?php define ( 'WRX_CLASS_DIR','/classes/'); function __autoload($sClassName) { static $sDirPath = null; if(is_null($sDirPath)) { $sDirPath = rtrim(realpath ( dirname(__FILE__).'/../'),DIRECTORY_SEPARATOR).WRX_CLASS_DIR; } $sNewClassName = $sClassName; if (substr ( $sNewClassName, 0, 3 ) == 'WRX') { $sNewClassName = substr ( $sNewClassName, 3 ); } $sFileName = $sDirPath . strtolower ( preg_replace ( '/([a-z])([A-Z])/', '$1/$2', $sNewClassName ) ) . '.php'; if (file_exists ( $sFileName )) { require_once $sFileName; } else { die ( "Не могу загрузить класс [" . $sClassName . "] из [" . $sFileName . "]" ); } } htdocs/index.php PHP: <?php require_once "../core/loader.php"; $a = $b; вывод Код (Text): WRX Exception: [0] WRX ENOTICE(8): Undefined variable: b WRX Exception: [/usr/www/*****/htdocs/index.php(5)] #0 /usr/www/*****/htdocs/index.php(5): WRXErrorHandler(8, 'Undefined varia...', '/usr/www/*****...', 5, Array) #1 {main}
iliavlad Вот-вот, "с записью в лог что-то не так", а когда вам понадобиться узнать что именно у вас не так, все равно придется в результате городить теже if (0 != ($result = doSomething()) topas А что здесь аргументировать-то? Большинство функций PHP возвращают на выходе TRUE/FALSE либо код ошибки. Если это есть, значем придумывать что-то еще? Apple А вдруг завтра конец света и никакая функция вам не поможет )) Я понимаю, что ошибки надо отслеживать, но не до абсурда-же это доводить. 440Hz, какой ужас, вы что всерьез этим пользуйтесь или это просто прикол такой?
KMB Вы отстаиваете свою точку зрения, пытаетесь переубедить X человек и при этом PHP: <?php ... try{ ob_start(); header('Content-Type: text/html; charset=utf-8'); Session::auto(); require_once 'etc/ElevantRouter.class.php'; Router::setPathClient(PATH_ROUTER); Router::setUrl($_SERVER['REQUEST_URI']); Router::instance('ElevantRouter'); require_once PATH_TEMPLATE . '/wrapper.php'; ob_end_flush(); } catch (RouterException $e){ ob_end_clean(); if ($e->getCode() === RouterException::NOT_FOUND_METHOD){ header('HTTP/1.0 404'); include('app/view/page404.html'); die; } exception_log($e); } catch (PageException $e){ ob_end_clean(); $e->handler(); die; } catch (Exception $e){ ob_end_clean(); header("HTTP/1.0 500 Internal Server Error"); include('app/view/page500.html'); exception_log($e); } ?> exception_log() в режиме отладки выводит трассировку на экран, в боевом режиме складывает ошибки в файловую систему Прекрасно работает.
topas, извините, может я действительно чего-то недопонимаю, но к чему все эти сложности с трассировкой, если в точности тоже самое итак автоматом пишется в лог-записи сервера? Открыл, прочел, - определил в чем проблема.
KMB Сложностей нет, есть удобный инструмент, я им пользуюсь. Не всегда в контексте метода или функции удаётся понять в чём же реальная ошибка. Например метод поиска пользователя по id. Мы знаем, что id не может быть по своей природе отрицательным, но в результате обработки скрипта в этот метод пришла именно минус единица. Одного взгляда на трассировку вполне достаточно, чтобы увидеть в каком месте произошел сбой. Ошибки, обычно, проявляются в дочерних функциях и методах. По поводу логов web-сервера: не каждый веб-сервер способен хранить POST-данные и PHP-сессию. А это входные данные, без которых порою трудно воспроизвести ошибку