Подавить ошибку с помощью оператора @в PHP

Как вы считаете, действительно ли используется оператор @для подавления ошибки/предупреждения в PHP, тогда как вы можете обрабатывать ошибку?

Если да, то в каких обстоятельствах вы бы это использовали?

Примеры кода приветствуются.

Изменить: отметить для ответчиков. Я не хочу отключать отчет об ошибках, но, например, обычной практикой является использование

@fopen($file);

а затем проверить потом... но вы можете избавиться от @, выполнив

if (file_exists($file))
{
    fopen($file);
}
else
{
    die('File not found');
}

или аналогичный.

Я предполагаю, что вопрос - есть ли где-нибудь, что @HAS используется для подавления ошибки, которая НЕ МОЖЕТ быть обработана каким-либо другим способом?

Ответ 1

Я бы подавил ошибку и обработал ее. В противном случае у вас может быть проблема TOCTOU (время проверки, время использования. Например, файл может быть удален после того, как file_exists вернет true, но до fopen).

Но я бы не просто подавил ошибки, чтобы заставить их уйти. Они лучше видны.

Ответ 2

Примечание. Во-первых, я понимаю, что 99% разработчиков PHP используют оператор подавления ошибок (я был одним из них), поэтому я ожидаю, что любой PHP-разработчик увидит, что это не согласуется.

Как вы считаете, действительно ли используется оператор @для подавления ошибки/предупреждения в PHP, тогда как вы можете обрабатывать ошибку?

Короткий ответ:
Нет!

Более правильный ответ:
Я не знаю, как я не все знаю, но до сих пор я не сталкивался с ситуацией, когда это было хорошим решением.

Почему это плохо:
Я думаю, что около 7 лет, используя PHP, я видел бесконечную агонию отладки, вызванную оператором подавления ошибок, и никогда не сталкивался с ситуацией, когда это было неизбежно.

Проблема в том, что фрагмент кода, который вы подавляете для ошибок, в настоящее время может вызывать только ошибку, которую вы видите; однако, когда вы меняете код, на который полагается подавленная линия, или среда, в которой она выполняется, тогда есть все шансы, что линия попытается вывести совершенно другую ошибку из той, которую вы пытались игнорировать. Тогда как вы отслеживаете ошибку, которая не выводится? Добро пожаловать в отладку ада!

Мне потребовалось много лет, чтобы понять, сколько времени я трачу каждые пару месяцев из-за подавленных ошибок. Чаще всего (но не исключительно) это было после установки сторонней script/app/library, которая была безошибочной в среде разработчиков, но не моя из-за разницы в конфигурации php или сервера или отсутствовала зависимость, которая обычно выводила бы ошибка, сразу же предупреждающая о проблеме, но не тогда, когда разработчик добавляет magic @.

Альтернативы (в зависимости от ситуации и желаемого результата):
Обращайтесь к фактической ошибке, о которой вы знаете, так что если часть кода вызовет определенную ошибку, то она не будет запущена в этой конкретной ситуации. Но я думаю, что вы получаете эту часть, и вы просто беспокоились о том, что конечные пользователи видят ошибки, и это то, что я сейчас адресую.

Для регулярных ошибок вы можете настроить обработчик ошибок, чтобы они выводились так, как вы хотите, когда вы просматриваете страницу, но скрыты от конечных пользователей и регистрируетесь, чтобы вы знали, какие ошибки запускают ваши пользователи.

Для фатальных ошибок установите display_errors в off (ваш обработчик ошибок по-прежнему запускается) в вашем php.ini и включите ведение журнала ошибок. Если у вас есть сервер разработки, а также живой сервер (который я рекомендую), этот шаг не требуется на вашем сервере разработки, поэтому вы можете отлаживать эти фатальные ошибки, не прибегая к просмотру файла журнала ошибок. Там даже трюк, использующий функцию выключения, чтобы отправить большое количество фатальных ошибок вашему обработчику ошибок.

Вкратце:
Пожалуйста, избегайте этого. Для этого может быть веская причина, но я еще не видел ее, поэтому до этого дня я считаю, что оператор (@) Error suppression является злым.

Вы можете прочитать мой комментарий на странице "Операторы контроля ошибок" в руководстве по PHP, если вы хотите получить дополнительную информацию.

Ответ 3

Да, подавление имеет смысл.

Например, команда fopen() возвращает FALSE, если файл не может быть открыт. Это прекрасно, но также создает предупреждающее сообщение PHP. Часто вы не хотите предупреждения - вы сами проверите FALSE.

Фактически руководство по PHP специально предлагает использовать @в этом случае!

Ответ 4

Если вы не хотите вызывать предупреждение при использовании таких функций, как fopen(), вы можете подавить ошибку, но использовать исключения:

try {
    if (($fp = @fopen($filename, "r")) == false) {
        throw new Exception;
    } else {
        do_file_stuff();
    }
} catch (Exception $e) {
    handle_exception();
}

Ответ 5

Следует избегать подавления ошибок, если вы не знаете, что можете обрабатывать все условия.

Это может быть намного сложнее, чем сначала.

Вам действительно нужно полагаться на php "error_log", чтобы быть вашим методом отчетности, так как вы не можете полагаться на просмотр пользователями страниц для сообщения об ошибках. (И вы также должны отключить php от отображения этих ошибок)

Тогда, по крайней мере, у вас будет исчерпывающий отчет о том, что все происходит неправильно в системе.

Если вы действительно должны обрабатывать ошибки, вы можете создать собственный обработчик ошибок

http://php.net/set-error-handler

Затем вы можете отправлять исключения (которые могут быть обработаны) и делать все, что необходимо для сообщения о странных ошибках для администрирования.

Ответ 6

Я НИКОГДА не позволяю себе использовать "@" ... период.

Когда я обнаруживаю использование "@" в коде, я добавляю комментарии, чтобы сделать это отчетливо очевидным, как в момент использования, так и в docblock вокруг функции, в которой он используется. Я тоже был укушен отладкой "преследовать призрак" из-за такого подавления ошибок, и я надеюсь, что это станет проще для следующего человека, выделив его использование, когда я его найду.

В тех случаях, когда я хочу, чтобы мой собственный код выдавал исключение, если встроенная функция PHP встречает ошибку, а "@" - это простой способ, я вместо этого хочу сделать что-то другое, результат (но еще раз), очевидный в коде:

$orig = error_reporting(); // capture original error level
error_reporting(0);        // suppress all errors
$result = native_func();   // native_func() is expected to return FALSE when it errors
error_reporting($orig);    // restore error reporting to its original level
if (false === $result) { throw new Exception('native_func() failed'); }

Это намного больше кода, который просто пишет:

$result = @native_func();

но я предпочитаю, чтобы мое подавление требовало ОЧЕНЬ ОБЫЧНОГО, ради бедной души отладки, которая следует за мной.

Ответ 7

Большинство людей не понимают значения сообщения об ошибке.
Без шуток. Большинство из них.

Они думают, что сообщения об ошибках одинаковы, говорит: "Что-то не так!"
Они не удосуживаются его прочитать.
Хотя это самая важная часть сообщения об ошибке, а не только факт ее поднятия, но это значение. Он может сказать вам, что происходит не так. Сообщения об ошибках предназначены для помощи, а не для того, чтобы беспокоить вас "как скрыть это?". проблема. Это одно из самых больших недоразумений в мире веб-программирования новичка.

Таким образом, вместо сообщения об ошибке gagging следует прочитать, что он говорит. Он имеет не только одно значение "файл не найден". Возможны тысячи ошибок: permission denied, save mode restriction, open_basedir restriction и т.д. Каждый из них требует соответствующих действий. Но если вы это сделаете, вы никогда не узнаете, что произошло!

OP представляет собой сообщение об ошибке с ошибкой обработки, в то время как это очень большая разница!
Обработка ошибок для пользователя. "здесь что-то случилось".
Хотя сообщения об ошибках предназначены для программистов, которым отчаянно нужно знать, что именно произошло.

Таким образом, никогда не печатайте сообщения об ошибках. И зарегистрировать его для программиста, а обработать его для пользователя.

Ответ 8

Не существует способа подавить предупреждения и ошибки php.ini? в этом случае вы можете отлаживать только изменение флага и не пытаться обнаружить, что @скрывает проблему.

Ответ 9

Использование @иногда является продуктивным. По моему опыту, вы всегда должны отключать отчет об ошибках в php.ini или вызывать

error_reporting(0);

на производственной площадке. Таким образом, когда вы находитесь в разработке, вы можете просто прокомментировать строку и сохранить видимые ошибки для отладки.

Ответ 10

Единственное место, где мне действительно нужно было использовать его, - это функция eval. Проблема с eval заключается в том, что когда строка не может быть проанализирована из-за синтаксической ошибки, eval не возвращает false, а скорее выдает ошибку, точно так же, как наличие ошибки синтаксического анализа в регулярном script. Чтобы проверить, является ли script, сохраненный в строке, синтаксический анализ, вы можете использовать что-то вроде:

$script_ok = @eval('return true; '.$script);

AFAIK, это самый элегантный способ сделать это.

Ответ 11

Одно место, которое я использую, это код сокета, например, если у вас установлен тайм-аут, вы получите предупреждение об этом, если вы не включите @, даже если он действителен, чтобы не получить пакет.

$data_len = @socket_recvfrom( $sock, $buffer, 512, 0, $remote_host, $remote_port )

Ответ 12

Вы не хотите подавлять все, так как он замедляет ваш script.

И да, есть способ как в php.ini, так и внутри вашего script удалить ошибки (но делать это только тогда, когда вы находитесь в живой среде и регистрируете свои ошибки с php)

<?php
    error_reporting(0);
?>

И вы можете прочитать this для версии php.ini отключения.

Ответ 13

Если вы используете настраиваемую функцию обработки ошибок и хотите подавить ошибку (возможно, известную ошибку), используйте этот метод. Использование "@" не является хорошей идеей в этом контексте, поскольку оно не будет подавлять ошибку, если установлен обработчик ошибок.

Напишите 3 функции и вызовите это.

# supress error for this statement
supress_error_start();  
$mail_sent = mail($EmailTo, $Subject, $message,$headers);
supress_error_end(); #Don't forgot to call this to restore error.  

function supress_error_start(){
    set_error_handler('nothing');
    error_reporting(0);
}

function supress_error_end(){
    set_error_handler('my_err_handler');
    error_reporting('Set this to a value of your choice');
}

function nothing(){ #Empty function
}

function my_err_handler('arguments will come here'){
      //Your own error handling routines will come here
}

Ответ 14

Я использую его при попытке загрузить файл HTML для обработки в качестве объекта DOMDocument. Если в HTML есть какие-то проблемы... и на каком веб-сайте нет хотя бы одного... DOMDocument- > loadHTMLFile() выкинет ошибку, если вы не подавите ее с помощью @. Это единственный способ (возможно, лучшие). Мне когда-либо удавалось создавать HTML-скребки в PHP.