Подавить ошибку с помощью оператора @ в PHP - PullRequest
67 голосов
/ 26 сентября 2008

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

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

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

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

@fopen($file);

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

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

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

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

Ответы [ 15 ]

116 голосов
/ 06 июня 2009

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

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

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

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

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

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

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

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

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

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

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

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

24 голосов
/ 26 сентября 2008

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

Но я бы не просто подавлял ошибки, чтобы они ушли. Это лучше быть видимым.

18 голосов
/ 26 сентября 2008

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

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

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

12 голосов
/ 26 сентября 2008

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

try {
    if (($fp = @fopen($filename, "r")) == false) {
        throw new Exception;
    } else {
        do_file_stuff();
    }
} catch (Exception $e) {
    handle_exception();
}
7 голосов
/ 16 июля 2009

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

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

В тех случаях, когда я хочу, чтобы мой собственный код выдавал исключение, если нативная функция 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();

но я предпочитаю, чтобы мое подавление нуждалось в ОЧЕНЬ ЯВНОМ, ради бедной отлаживающей души, которая следует за мной.

6 голосов
/ 26 сентября 2008

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

Это может быть намного сложнее, чем кажется на первый взгляд.

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

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

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

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

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

5 голосов
/ 06 октября 2010

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

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

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

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

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

3 голосов
/ 21 июля 2009

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

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

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

3 голосов
/ 26 сентября 2008

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

error_reporting(0);

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

3 голосов
/ 26 сентября 2008

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

...