Как осуществлять подавление ошибок в PHP?
Но ведь тоже самое, можно написать компактнее, воспользовавшись подавлением ошибки доступа к элементам массива. В случае ошибки будет возвращен null.
$v = @$arr[‘a’][‘b’][‘c’];
Почему многие предпочитают первый способ? Религия не позволяет использовать подавление ошибок даже для минимального выражения? Или есть еще какие-то причины?
Оценить 1 комментарий
Мне привели упрощенные способы типа:
$v = isset($arr[‘a’][‘b’][‘c’]) ? $arr[‘a’][‘b’][‘c’] : null;
Но, все равно, здесь нужно будет повторить выражение $arr[‘a’][‘b’][‘c’] дважды. Сначала для проверки на наличие элемента, а потом для доступа. И в приведенном примере выражение очень простое. А может быть что то мудреное, типа:
$arr[$tables[$t][‘name’]][‘rows’][$r][‘cols’][$c][‘format’][‘borders’][‘top’]
Даже в вашем примере, нужно будет повторить выражение $arr[‘a’][‘b’][‘c’] дважды. Сначала для проверки на наличие элемента, а потом для доступа. И в приведенном примере выражение очень простое. А может быть что то мудреное, типа:
$arr[$tables[$t][‘name’]][‘rows’][$r][‘cols’][$c][‘format’][‘borders’][‘top’]
Начиная с верии 5.3, тернарный оператор в PHP допускает сокращенную запись, то есть позволяет опустить среднюю часть, если условие истинно.
@andymitrich Ваш синтаксис не корректен, при отсутствии $arr[‘a’] либо $arr[‘a’][‘b’] получите ошибку
@nazarpc Позвольте не согласиться — мой синтаксис корректен. В приведенном отрезке кода я не использую никаких запрещенных в PHP конструкций — вероятно, вы выражаетесь не корректно.
Далее, перед тем как опубликовать здесь этот код, я опробовал его у себя на локальной машине и проверил — советую вам впредь делать то же самое, тогда, возможно, надобность в таких комментариях отпадет.
@andymitrich Действительно, прошу прощения. Почему-то всегда был уверен, что вложенные нужно проверять поэлементно.
если есть ошибка, ее нужно устранить, а не подавить. Подавление ошибок — один из признаков говнокода.
Не устранить, а гарантированно поймать. Ведь не считается грехом запихивать участок кода в try-catch.
В приведенном примере, хоть формально и выполняется подавление, но на практике ошибка обрабатывается путем возврата значения null. Последующий код, разумеется должен быть расcчитан на значение null.
$v = isset($arr['a']['b']['c']) ? $arr['a']['b']['c'] : null;
вот здесь автор предлагает несколько решений, объясняет подводные камни nikic.github.io/2014/01/10/The-case-against-the-if.
а если начать использовать @, то можно потерять действительно нужные ошибки и отладка станет очень тяжелой. Представьте, ничего плохого не произойдёт, если вы одну-единственную переменную в проекте назовёте $a; Но если таких переменных будет много, код станет невыносимым. Здесь похоже такая же логика.
$arr[$tables[$t][‘name’]][‘rows’][$r][‘cols’][$c][‘format’][‘borders’][‘top’] — это конечно 3.14здец товарищи, но такая конструкция мне никогда не встречалась.
1) Наглядно видно что происходит в скрипте (есть ключ? нет — ставим default)
2) Упрощает отладку в дальнейшем. «@» скрывает ВСЕ ошибки.
3) Потому, что оператор «@» замедляет выполнение конструкции вида iffset(key) ? key : default в два раза. Даже если ошибки не возникает.
И если уж исходить из редких ситуаций. Представьте насколько замедлится скрипт при прохождении 100000 элементов.
Может и 3.14здец, но достаточно типично, при сабмите сложных форм с табличными, списочными и вложенными под-формами. К тому же доверять корректности пришедшей структуре нельзя.
$v = isset($arr['a']['b']['c']) ? $arr['a']['b']['c'] : null;
Потому что:
1) сразу понятно что имелось ввиду
2) быстрее
3) ошибки нужно не допускать, а допускать и подавлять сознательно — очень плохой тон, не сразу понятно что вы ожидали получить в результате, это быдлокод, не поддающийся отладке
4) становится похоже на то, что вы вообще не понимаете, что происходит и решили просто убрать отображение ошибки, то что вы там ожидаете null не очевидно чуть менее чем полностью
$arr[$tables[$t]['name']]['rows'][$r]['cols'][$c]['format']['borders']['top']
Страшновато, но программирование не всегда белое и пушистое. Можно либо циклом проверять, либо заняться рефакторингом и сделать более удобную для работы структуру.
Оператор подавления ошибок в PHP
В PHP имеется оператор подавления ошибок. В большинстве случаев это нужно для того, чтобы по-своему обработать ошибку. Давайте разберём с Вами оператор подавления ошибок в PHP более подробно.
Оператор подавления ошибок (пишется он так «@«) служит для запрета вывода информации об этих ошибках. Использовать данный оператор можно рядом с тем, что возвращает результат. Например, перед различными функциями, переменными и прочим. Перед служебными конструкциями его нельзя использовать, поскольку они ничего не возвращают. К таким конструкциям относятся циклы, условные операторы, объявления функций и классов.
Теперь пример использования оператора подавления ошибок в PHP:
$handler = @fopen(«my_file.txt», «r»);
if (!$handler) echo «Ошибка при открытии файла»;
Файла my_file.txt не существует. И если мы уберём «@«, то у нас выведется ошибка, которая нам совсем не нужна, поскольку мы по-своему обрабатываем случай, если файл не открывается или не существует.
Второй очень популярный пример использования «@» при подключении к базе данных:
$mysqli = @new mysqli(«localhost», «root», «123», «mydb»);
if ($mysqli->connect_errno) echo «Ошибка при подключении»;
В данном случае мы указали неверные данные для подключения к базе данных. Если мы уберём «@«, то PHP нам сразу же выведет ошибку. Однако, мы хотим её обработать сами, поэтому ставим оператор подавления ошибок, а после уже смотрим: возникли ошибки или нет.
Я показал только 2 самых популярных примера использования оператора подавления ошибок в PHP, на практике же есть ещё масса примеров использования данного оператора. Однако, использовать его только для того, чтобы убрать постоянно возникающие ошибки на сайте, не стоит, так как это уже, скорее всего, ошибка в самом коде.
Создано 14.06.2013 04:23:49
Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!
Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
- Кнопка:
Она выглядит вот так: - Текстовая ссылка:
Она выглядит вот так: Как создать свой сайт - BB-код ссылки для форумов (например, можете поставить её в подписи):
Комментарии ( 4 ):
Михаил, какие нужно устанавливать настройки, как следует обрабатывать ошибки на «боевом» сервере, чтобы пользователю показать красивую страничку с ошибкой, и записать текст ошибки в файл?
находил функции error_log, set_error_handler, trigger_error, но применения им не нашел. Возможно нужно отключить вывод ошибок, установить свой обработчик ошибок, который будет вести логи и выводить ошибку пользователю?
Php оператор подавления ошибок
@print($a);
is equivalent to
if isset($a) echo $a ;
@a++;
is equivalent to
if isset($a) $a++ ;
else $a = 1;
It’s still possible to detect when the @ operator is being used in the error handler in PHP8. Calling error_reporting() will no longer return 0 as documented, but using the @ operator does still change the return value when you call error_reporting().
My PHP error settings are set to use E_ALL, and when I call error_reporting() from the error handler of a non-suppressed error, it returns E_ALL as expected.
But when an error occurs on an expression where I tried to suppress the error with the @ operator, it returns: E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR (or the number 4437).
I didn’t want to use 4437 in my code in case it changes with different settings or future versions of PHP, so I now use:
function my_error_handler ( $err_no , $err_msg , $filename , $linenum ) if ( error_reporting () != E_ALL ) return false ; // Silenced
>
// .
>
?>
If the code needs to work with all versions of PHP, you could check that error_reporting() doesn’t equal E_ALL or 0.
And, of course, if your error_reporting settings in PHP is something other than E_ALL, you’ll have to change that to whatever setting you do use.
After some time investigating as to why I was still getting errors that were supposed to be suppressed with @ I found the following.
1. If you have set your own default error handler then the error still gets sent to the error handler regardless of the @ sign.
2. As mentioned below the @ suppression only changes the error level for that call. This is not to say that in your error handler you can check the given $errno for a value of 0 as the $errno will still refer to the TYPE(not the error level) of error e.g. E_WARNING or E_ERROR etc
3. The @ only changes the rumtime error reporting level just for that one call to 0. This means inside your custom error handler you can check the current runtime error_reporting level using error_reporting() (note that one must NOT pass any parameter to this function if you want to get the current value) and if its zero then you know that it has been suppressed.
// Custom error handler
function myErrorHandler ( $errno , $errstr , $errfile , $errline )
if ( 0 == error_reporting () ) // Error reporting is currently turned off or suppressed with @
return;
>
// Do your normal custom error reporting here
>
?>
For more info on setting a custom error handler see: http://php.net/manual/en/function.set-error-handler.php
For more info on error_reporting see: http://www.php.net/manual/en/function.error-reporting.php
Be aware that using @ is dog-slow, as PHP incurs overhead to suppressing errors in this way. It’s a trade-off between speed and convenience.
If you use the ErrorException exception to have a unified error management, I’ll advise you to test against error_reporting in the error handler, not in the exception handler as you might encounter some headaches like blank pages as error_reporting might not be transmitted to exception handler.
function exception_error_handler ( $errno , $errstr , $errfile , $errline )
throw new ErrorException ( $errstr , 0 , $errno , $errfile , $errline );
>
function catchException ( $e )
if ( error_reporting () === 0 )
return;
>
function exception_error_handler ( $errno , $errstr , $errfile , $errline )
if ( error_reporting () === 0 )
return;
>
throw new ErrorException ( $errstr , 0 , $errno , $errfile , $errline );
>
function catchException ( $e )
// Do some stuff
>
Оператор управления ошибками
PHP поддерживает один оператор управления ошибками: знак (@). В случае, если он предшествует какому-либо выражению в PHP-коде, любые сообщения об ошибках, генерируемые этим выражением, будут проигнорированы.
Если вы установили собственную функцию обработки ошибок с помощью set_error_handler() , то она все равно будет вызвана, однако, если внутри этой функции будет вызвана функция error_reporting() , то она вернет 0, если функция, вызвавшая данную ошибку, была подавлена с помощью @.
В случае, если установлена опция track_errors , все генерируемые сообщения об ошибках будут сохраняться в переменной $php_errormsg . Эта переменная будет перезаписываться при каждой новой ошибке, поэтому в случае необходимости проверяйте ее сразу же.
// Преднамеренная ошибка при работе с файлами
$my_file = @ file ( ‘non_existent_file’ ) or
die ( «Ошибка при открытии файла: сообщение об ошибке было таким: ‘ $php_errormsg ‘» );
?php
// работает для любых выражений, а не только для функций
$value = @ $cache [ $key ];
// В случае если ключа $key нет, сообщение об ошибке (notice) не будет отображено
Замечание: Оператор @ работает только с выражениями. Есть простое правило: если что-то возвращает значение, значит вы можете использовать перед ним оператор @. Например, вы можете использовать @ перед именем переменной, произвольной функцией или вызовом include , константой и так далее. В то же время вы не можете использовать этот оператор перед определением функции или класса, условными конструкциями, такими как if, foreach и т.д.
Также ознакомьтесь с описанием функции error_reporting() и разделом руководства Обработка ошибок и функции логирования.
На сегодняшний день оператор «@» подавляет вывод сообщений даже о критических ошибках, прерывающих работу скрипта. Помимо всего прочего, это означает, что если вы использовали «@» для подавления ошибок, возникающих при работе какой-либо функции, в случае если она недоступна или написана неправильно, дальнейшая работа скрипта будет остановлена без каких-либо уведомлений.