Комментарии 75
Небольшое улучшение по обработке фатальных ошибок:
// clean all buffers
while (ob_get_level()) {
ob_end_clean();
}
+5
>function error_handler
никогда так не делайте. кидайте ErrorException и обрабатывайте его.
никогда так не делайте. кидайте ErrorException и обрабатывайте его.
-5
>echo "{$errors[$errno]}[$errno] $errstr ($errfile на $errline строке)
\n";
так же очень хочется видеть стек вызовов, входные параметры, разную логику в девелоперском и рабочем окружении
\n";
так же очень хочется видеть стек вызовов, входные параметры, разную логику в девелоперском и рабочем окружении
-2
1. Включайте трейс в начале скрипта, получайте стек в обработчике, кто мешает?
2. Ну обьявите окружение, в зависимости от окружения обрабатывайте
Эта статья — не пример использования, а гайд для тех кто желает разобратся. А уж используйте сами как хотите.
2. Ну обьявите окружение, в зависимости от окружения обрабатывайте
Эта статья — не пример использования, а гайд для тех кто желает разобратся. А уж используйте сами как хотите.
+1
Для фатальных ошибок трейс перестанет существовать так как текущий контекст исполнения уничтожается.
0
Действительно ли отдельная от исключений обработка ошибок имеет смысл? Не слишком ли это все запутано? Не собираются ли разработчики PHP от нее избавляться?
0
хотят наверное, но не могут. ибо порушится половина сайтов где эти ошибки сейчас просто гасятся собаками или настройками php.ini. обратная совместимость чтоб её. может с выносом всех функций о отдельные неймспейс php и можно будет такое сделать. но сейчас точно нет.
+1
Это вопрос к разработчикам. А пока не избавились иногда без этого всего просто никуда.
0
Имеет, например, нет смысла бросать исключения в случае E_NOTICE (тем более в случаях E_STRICT или E_DEPRECATED), а сигнализировать об ошибке полезно.
0
Хм, давно уже не видел людей игнорирующих нотайсы…
0
Посмотрите на IP.Board (http://community.invisionpower.com/) их даже за ошибки не считают :) но вообще я не говорил что их нужно игнорировать, но вот выкидывать исключения это слишком, ИМХО.
0
Ну почему в других языках это не «слишком» а вот конкретно в случае пхп становится «слишком»? :)
+1
В каких других языках с динамической типизацией E_NOTICE при пропуске переменной или E_STRICT или тем более E_DEPRECATED выбрасывают исключение или приводит к фатальным ошибкам?
0
Не совсем понял что вы имеете в виду под «пропуском переменной».
Но если вам так нужен пример к моему коментарию — несуществующий индекс выбросит исключение в питоне, и это нормально.
Но если вам так нужен пример к моему коментарию — несуществующий индекс выбросит исключение в питоне, и это нормально.
0
> Не совсем понял что вы имеете в виду под «пропуском переменной»
Индекс как в вашем примере или свойство объекта или просто переменная с очепяткой.
> несуществующий индекс выбросит исключение в питоне
Но не выбросит в javascript и это тоже нормально.
PS: критичные ошибки (с E_WARNING) лично мне были бы удобнее в виде исключений.
Индекс как в вашем примере или свойство объекта или просто переменная с очепяткой.
> несуществующий индекс выбросит исключение в питоне
Но не выбросит в javascript и это тоже нормально.
PS: критичные ошибки (с E_WARNING) лично мне были бы удобнее в виде исключений.
0
Давайте я открою вам глаза…
Ну и контрольный в голову:
<script>
foo={}
if(foo.bar == false) {
alert("You won't see me!");
}
</script>
<?php
Class Foo
{
}
$bar = new Foo();
if($bar->baz == false && $not_defined_var == false)
{
echo "BINGO!";
}
Ну и контрольный в голову:
<script>
try {
if(not_defined_var == false) {
}
} catch (e) {
alert('HAHA!');
}
</script>
0
Не совсем понятно что именно вы хотели показать этими примерами?
1) undefined в js для неопределенных свойств (вообще никаких предупреждений)
2) особенности приведения типов в PHP (тут хоть нотис есть)
3) необходимость явного объявления в переменных в js
1) undefined в js для неопределенных свойств (вообще никаких предупреждений)
2) особенности приведения типов в PHP (тут хоть нотис есть)
3) необходимость явного объявления в переменных в js
+1
Я хотел сказать что некорректно сравнивать php с js, особенно так как это сделали вы:
Или по вашему поведение типа «не, ну переменная конечно не определена но все равно она равна false потому что я так захотел» это нормально? )
Ну а в последнем примере «просто переменная с очепяткой» выбрасывающая исключение :)
> несуществующий индекс выбросит исключение в питоне
Но не выбросит в javascript и это тоже нормально.
Или по вашему поведение типа «не, ну переменная конечно не определена но все равно она равна false потому что я так захотел» это нормально? )
Ну а в последнем примере «просто переменная с очепяткой» выбрасывающая исключение :)
0
Как заметили выше, есть не только E_NOTICE, но и E_STRICT и E_DEPRECATED. А ещё есть тонны устаревшего кода, который работает и который никто в здравом уме переписывать не будет. Зато будут обновлять версии пхп, дабы улучшить производительность или закрыть дыры в безопасности.
Главная особенность исключений в том, что они фатальны, если не перехвачены. Поэтому не получится просто взять и поменять старую систему ошибок на новую.
Если интересно, вот мнение расмуса на этот счёт.
Главная особенность исключений в том, что они фатальны, если не перехвачены. Поэтому не получится просто взять и поменять старую систему ошибок на новую.
Если интересно, вот мнение расмуса на этот счёт.
0
Приезжайте к нам в офис — покажу двух
+1
Так же как и с ошибками, на что генерировать, а на что нет, должно решаться в настройках, по-моему.
0
Ну, в error_handler вы можете генерировать исключения, более того есть стандартный класс ErrorException, спроектированный специально для этого (в мануале есть пример его использования в этих целях). Несколько строк в начале скрипта и все перехватываемые ошибки будут генерировать исключение, которые можно ловить в месте вызова.
В принципе, наверное, не сложно добавить ini параметр для автоматической генерации, но вряд ли это будет скоро по дефолту.
В принципе, наверное, не сложно добавить ini параметр для автоматической генерации, но вряд ли это будет скоро по дефолту.
0
Курсовую писали?
+8
нет) хотя соглашусь, что похоже.
на самом деле, хотел сделать небольшой обзор механизма обработки ошибок в кохане (с демонстрацией своего мини-модуля), а как начал копать — не смог остановиться и вот результат ))
хотя от первоначальной идеи не отказываюсь — думаю все же написать обзор, как логическое продолжение этой статьи
на самом деле, хотел сделать небольшой обзор механизма обработки ошибок в кохане (с демонстрацией своего мини-модуля), а как начал копать — не смог остановиться и вот результат ))
хотя от первоначальной идеи не отказываюсь — думаю все же написать обзор, как логическое продолжение этой статьи
+1
про кохану было бы интересно, можно ли ждать поста именно с конахой связанного?
0
ждать конечно можно, но вот точной датой я вас обрадовать не могу. Кто бы мог подумать, но написание статьи отнимает приличное время…
0
Для 3.2 писал класс перехвата ошибок. Для ajax-а отправлялся json с ошибкой, для CLI текст. Для обычного запроса — выводилась специальная страница ошибки (в зависимости от типа).
Для версии 3.3 все стало несколько проще… Или сложнее — кому как.
Там теперь можно реализовать метод get_response() в классе *_Exception а в переопределенном Kohana_Exception переопределить статический метод response, который отвечает построение «ответа» ошибки.
Для версии 3.3 все стало несколько проще… Или сложнее — кому как.
Там теперь можно реализовать метод get_response() в классе *_Exception а в переопределенном Kohana_Exception переопределить статический метод response, который отвечает построение «ответа» ошибки.
0
>при использовании оператора "@" error_reporting() вернет 0
предлагаю при использовании "@" сразу руки отрывать использующему :)
А вообще да, статья полезная для тех кто еще не в курсе, все четко и ясно.
Где вы были 3 года назад когда ну очень надо было а доков почти не было? ))
предлагаю при использовании "@" сразу руки отрывать использующему :)
А вообще да, статья полезная для тех кто еще не в курсе, все четко и ясно.
Где вы были 3 года назад когда ну очень надо было а доков почти не было? ))
+2
По поводу @ согласен, но… бывают ситуации разные.
Вот вам пример:
В случае если вдруг не получилось приконнектиться будет Warning: fsockopen(): unable to connect to
И как же нужно красиво и правильно обрабатывать такую ситуацию без собачки, чтобы ничего лишнего не было в ответе даже на девелоперской машине (т.к. это может, например, попортить json)? Чем тут так плоха собачка @?
Вот вам пример:
$fp = fsockopen($host, $port, $errno, $errstr);
if (!$fp) {
echo "ERROR: $errno - $errstr<br />\n";
} else {
fwrite($fp, "\n");
echo fread($fp, 128);
fclose($fp);
}
В случае если вдруг не получилось приконнектиться будет Warning: fsockopen(): unable to connect to
И как же нужно красиво и правильно обрабатывать такую ситуацию без собачки, чтобы ничего лишнего не было в ответе даже на девелоперской машине (т.к. это может, например, попортить json)? Чем тут так плоха собачка @?
+1
А зачем, извините, использовать безбожно устаревший инструментарий?
Не бывает таких ситуаций:
php.net/manual/en/function.socket-connect.php
php.net/manual/ru/function.stream-socket-client.php
Кстати в случае с последним вам только вызов подключения поменять придется, остальной код не изменится.
Не бывает таких ситуаций:
php.net/manual/en/function.socket-connect.php
php.net/manual/ru/function.stream-socket-client.php
Кстати в случае с последним вам только вызов подключения поменять придется, остальной код не изменится.
0
Разве эти функции не генерируют warnings?
+1
Как это не странно — нет, не генерируют :)
-1
Обе эти функции еще как генерируют варнинги. Можете сами проверить (только показ варнингов включите).
Вот например: PHP Warning: socket_connect(): unable to connect
И как же быть? Собачка в этом случае всё равно такое зло? Если да, то чем же?
Вот например: PHP Warning: socket_connect(): unable to connect
И как же быть? Собачка в этом случае всё равно такое зло? Если да, то чем же?
0
Как я уже написал — был не прав. С тем что собака не зло — не соглашусь никогда после того как неделю искал ошибку что притаилась за @session_start написанным каким-то умником в огромном проекте.
+1
О собаках. Я прекрасно понимаю потенциальный вред, который они могут нанести. Но считаю что следует поступать рационально, нежели как гласят какие-то догмы.
Случаи типа
не рассматриваем. Здесь любой мало-мальски опытный программист увидит зло.
Но представим ситуацию: нужно удалить файл, если он есть. Если мы сделаем так:
Есть вероятность, что файл может быть удален другим скриптом, между проверкой и удалением — получим
А так не получим:
Пример выше зависит от того установлен ли обработчик ошибок и того как он работает.
Едем дальше. В последнее время, все чаще прихожу к выводу, что написание
тупо удобнее и лаконичнее, чем
Хотелось бы услышать конструктивную критику приведенных примеров.
Случаи типа
@mysql_connect($host, $user, $pass) or die();
не рассматриваем. Здесь любой мало-мальски опытный программист увидит зло.
Но представим ситуацию: нужно удалить файл, если он есть. Если мы сделаем так:
if (file_exists($file)) unlink($file);
Есть вероятность, что файл может быть удален другим скриптом, между проверкой и удалением — получим
warning
.А так не получим:
@unlink($file);
Пример выше зависит от того установлен ли обработчик ошибок и того как он работает.
Едем дальше. В последнее время, все чаще прихожу к выводу, что написание
$name = @$_GET['name'] ?: $defaultName;
тупо удобнее и лаконичнее, чем
$name = isset($_GET['name']) ? $_GET['name'] : $defaultName;
Хотелось бы услышать конструктивную критику приведенных примеров.
0
+4
Кстати, да. Это тоже удобно. Спасибо, что напомнили.
0
А Вы как считаете,
@
хуже чем isset
? Т.е. Вы бы мне руки оторвали за такую запись?0
Хотелось бы услышать конструктивную критику приведенных примеров.Использование @ для подавления ошибок снижает производительность. Иногда этим можно пренебречь иногда нет.
0
В php 5.4 над этим поработали.
0
AndrewStephanoff, не особо в курсе, но разница на простом тесте 0.2-0.3 секунды. PHP 5.4.9.
+1
Спасибо за тест, я сам не проверял — помню по мотивам презентации Змиевского. Видимо раньше было ещё хуже :D
0
А что за тест такой?
Тест:
Результат PHP 5.3:
Результат PHP 5.4:
Тест:
<?php
$count = 100000;
$t = microtime(1);
for ($i = 0; $i < $count; $i++) {
$zzz = isset($xxx);
}
$t = microtime(1) - $t;
echo "isset: $t<br>";
$t = microtime(1);
for ($i = 0; $i < $count; $i++) {
$zzz = @$xxx;
}
$t = microtime(1) - $t;
echo "@: $t<br>";
Результат PHP 5.3:
isset: 0.0094430446624756
@: 0.080410003662109
Результат PHP 5.4:
isset: 0.0065739154815674
@: 0.059032201766968
0
Итого, чтобы замедлить скрипт Вам понадобится сто тысяч собак :)
Но, конечно же, эти тесты не говорят ни-че-го. Абсолютно. Медлительность собаки зависит от обработчика ошибок (мы помним, что он запускается всегда). А значит если мы сделаем:
результаты теста очень сильно изменятся :)
Но, конечно же, эти тесты не говорят ни-че-го. Абсолютно. Медлительность собаки зависит от обработчика ошибок (мы помним, что он запускается всегда). А значит если мы сделаем:
set_error_handler(function() {
sleep(1000);
});
результаты теста очень сильно изменятся :)
0
У вас результат еще хуже, чем у меня :) (значения с @ и без отличаются практически на порядок).
Тест простой:
+ будет райзиться ошибка в кастомном хендлере, если он есть (это дополнительный тормоз)
+ сложнее дебажить
+ ошибки надо исправлять, а не прятать :)
Тест простой:
% cat test1.php
<?php
function x() { }
for ($i = 0; $i < 1000000; $i++) { x(); }
% time php test1.php
php test1.php 1,24s user 0,03s system 69% cpu 1,833 total
% cat test2.php
<?php
function x() { }
for ($i = 0; $i < 1000000; $i++) { @x(); }
% time php test2.php
php test2.php 1,51s user 0,03s system 75% cpu 2,059 total
+ будет райзиться ошибка в кастомном хендлере, если он есть (это дополнительный тормоз)
+ сложнее дебажить
+ ошибки надо исправлять, а не прятать :)
+1
будет райзиться ошибка в кастомном хендлере, если он есть (это дополнительный тормоз)
Это верно. Стоит уточнить, что обработчик будет срабатывать только при ошибке. Т.е. код вида
@foo($bar);
без ошибки будет трансформироваться в
$e = error_reporting(0);
foo($bar);
error_reporting($e);
а с ошибкой в
$e = error_reporting(0);
foo($bar);
error_handler();
error_reporting($e);
сложнее дебажить
В общем случае — да. Но если возникают подозрения, делается простой
grep @
по коду и в обработчике ошибок начинаем логировать/выводить все подряд.ошибки надо исправлять, а не прятать
@ != "прятать", @ == "подавлять вывод"
А исправлять конечно надо.
0
@ != «прятать», @ == «подавлять вывод»По дефолту (если нет своего хендлера) именно прятать. Поскольку подавленный вывод даже в логе (error_log) не осядет.
делается простой grep @ по кодуДля этого у меня есть xdebug с опцией scream :)
Стоит уточнить, что обработчик будет срабатывать только при ошибке.Верно. Но даже без ошибок мы получаем накладные расходы, которых можно избежать.
0
подавленный вывод даже в логе (error_log) не осядет.
Кстати, да. Это очень важно.
Для этого у меня есть xdebug с опцией scream
Точно! Это я видел, но еще не пробовал.
даже без ошибок мы получаем накладные расходы
Однозначно.
Я, в принципе, согласен по всем пунктам. Приятно общаться со знающими людьми.
0
Это все-таки не аргумент, а фуфло.
Особенно при наличии нормальных аргументов.
Особенно при наличии нормальных аргументов.
0
Есть вероятность, что файл может быть удален другим скриптом, между проверкой и удалением — получим warning.
То есть то что файл удалился не тем скриптом который его должен был удалить — это нормально и у нас все хорошо, да?
Со стороны выглядит примерно так:
1. Какая-то гадость удаляет мои файлы
2.
3. проигнорим мы это дело…
-1
Не выглядит. Файл удаляется этим же скриптом. Обычный Race Condition.
Я Вас понимаю. И не призываю тыкать собаку везде и всюду. Но, Вам тоже не стоит быть таким категоричным. Нужно смотреть зрело, т.е. осознавать к чему это приводит.
Кстати, в Вашей ситуации с сессией, можно было в обработчике ошибок логировать (или выводить) все подряд, тогда бы Вы не тратили столько времени. «Засобаченая» ошибка в любом случае попадает в обработчик.
С тем что собака не зло — не соглашусь никогда после того как неделю искал ошибку что притаилась за @session_start написанным каким-то умником в огромном проекте.
Я Вас понимаю. И не призываю тыкать собаку везде и всюду. Но, Вам тоже не стоит быть таким категоричным. Нужно смотреть зрело, т.е. осознавать к чему это приводит.
Кстати, в Вашей ситуации с сессией, можно было в обработчике ошибок логировать (или выводить) все подряд, тогда бы Вы не тратили столько времени. «Засобаченая» ошибка в любом случае попадает в обработчик.
+1
Критика очень простая.
Типичный похапешник воображает, что ошибка бывает всегда только одна. Та, про которую он, похапешник, случайно узнал.
Мысль о том, что могут встречаться и другие ошибки, никогда не приходит ему в голову.
И по этой причине он начинает считать себя хитрее и умнее всех.
Ровно до тех пор, когда файл невозможно будет удалить не потому что кто-то успел раньше, а потому что нет прав на удаление или имя файла указано неверно.
В итоге наш похапешник имеет неработающее приложение и ни малейшей идеи — почему.
Типичный похапешник воображает, что ошибка бывает всегда только одна. Та, про которую он, похапешник, случайно узнал.
Мысль о том, что могут встречаться и другие ошибки, никогда не приходит ему в голову.
И по этой причине он начинает считать себя хитрее и умнее всех.
Ровно до тех пор, когда файл невозможно будет удалить не потому что кто-то успел раньше, а потому что нет прав на удаление или имя файла указано неверно.
В итоге наш похапешник имеет неработающее приложение и ни малейшей идеи — почему.
0
Согласен. А что это вы решили написать в прошлое :)?
0
На эту статью сослался очередной терпила на тостере.
Огорчило, что такие позорные статьи висят на хабре, на тему «самый извращенный способ заменить display_errors=0 в php.ini»
А про собаку уж так — под руку пришлось.
Огорчило, что такие позорные статьи висят на хабре, на тему «самый извращенный способ заменить display_errors=0 в php.ini»
А про собаку уж так — под руку пришлось.
0
Ого, подняли тему из пепла)
Хотелось бы получить ссылку на вопрос с тостера, чтобы понять контекст вопроса + больше аргументов.
В статье нет призыва использовать собаку или игнорировать ошибки.
Огорчило, что такие позорные статьи висят на хабре, на тему «самый извращенный способ заменить display_errors=0 в php.ini»
Хотелось бы получить ссылку на вопрос с тостера, чтобы понять контекст вопроса + больше аргументов.
В статье нет призыва использовать собаку или игнорировать ошибки.
0
Забавно — а вот буквально только что сослались на перевод про ODKU :)
0
С перехватом фатальной ошибки есть небольшой нюанс. Если вы захотите посмотреть стек вызова через debug_print_backtrace(), то увидите, что точка входа в программу — вызов register_shutdown_function(). Чтобы посмотреть нормальный стек вызова, нужно использовать xdebug_get_function_stack() (требует xdebug).
+2
Это точно? Независимо от указанных в set_error_handler классов ошибок? Как-то не обращал внимания, наверное @ крайне редко использую :)
0
Если вы установили собственную функцию обработки ошибок с помощью set_error_handler(), то она все равно будет вызвана, однако, если внутри этой функции будет вызвана функция error_reporting(), то она вернет 0, если функция, вызвавшая данную ошибку, была подавлена с помощью @.
0
Упс, там цитата должна была быть :)
0
да, конечно зависит. если подавляемая ошибка не входит в класс ошибок определенных в set_error_handler(), то функция не будет вызвана.
здесь я хотел заострить внимание на том, что собака не работает как «выключатель» нашего обработчика и этот момент надо учитывать
здесь я хотел заострить внимание на том, что собака не работает как «выключатель» нашего обработчика и этот момент надо учитывать
+1
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Ошибки PHP: классификация, примеры, обработка