Яке використання символу @ в PHP?


577

Я бачив використання @певних функцій, таких як:

$fileHandle = @fopen($fileName, $writeAttributes);

У чому полягає використання цього символу?


3
І РічіХіндл, і Ейден Белл дали правильну відповідь, але оскільки я можу встановити лише одну відповідь як прийняту, я оберу першу. Вибачте Ейден
sv_in

1
Пригнічуючи помилки (хоча хороший) може привести до помилок в майбутньому при збереженні кодової бази ... stackoverflow.com/a/7116175/282343
dennismonsewicz

Відповіді:


636

Він пригнічує повідомлення про помилки - див. Оператори керування помилками в посібнику PHP.


46
Це було трохи швидкого розіграшу!
Ейден Белл

6
Так; до другого! Мені довелося перевірити ідентифікатори відповідей, щоб побачити, хто перший прийшов :)
Сампсон,

3
Я встиг виправити написання придушити після публікації ... і чорт за те, що покращити посилання одночасно вирує : P
Aiden Bell

1
Класна функція. Це робить використання isset()"зайвим", щоб уникнути undefined offsetпомилок.
WM

470

Це пригнічує помилки.

Див. Оператори управління помилками в посібнику:

PHP підтримує одного оператора управління помилками: знак at (@). Якщо буде надано вираз у PHP, будь-які повідомлення про помилки, які можуть бути згенеровані цим виразом, ігноруються.

Якщо ви встановили функцію користувальницької обробки помилок за допомогою set_error_handler (), вона все одно буде викликатися, але цей користувальницький обробник помилок може (і повинен) викликати error_reporting (), який поверне 0, коли виклику, який викликав помилку, передував @ ...


157
прихильний лише тому, що інша відповідь - це отримання любові.
ajacian81

10
19 позаду ... давай люди поб'ємо RichieHindle: P
Ейден Белл

Ця відповідь була першою (У контексті того, хто перший відповів на неї).
Мохд Абдул Муджіб

227

@Символ є контроль помилок оператора ( так званий «мовчання» або «закриті вгору» оператор). Це змушує PHP придушувати будь-які повідомлення про помилки (повідомлення, попередження, фатальні тощо), породжені відповідним виразом. Він працює так само, як унарний оператор, наприклад, він має пріоритет і асоціативність. Нижче наведено кілька прикладів:

@echo 1 / 0;
// generates "Parse error: syntax error, unexpected T_ECHO" since 
// echo is not an expression

echo @(1 / 0);
// suppressed "Warning: Division by zero"

@$i / 0;
// suppressed "Notice: Undefined variable: i"
// displayed "Warning: Division by zero"

@($i / 0);
// suppressed "Notice: Undefined variable: i"
// suppressed "Warning: Division by zero"

$c = @$_POST["a"] + @$_POST["b"];
// suppressed "Notice: Undefined index: a"
// suppressed "Notice: Undefined index: b"

$c = @foobar();
echo "Script was not terminated";
// suppressed "Fatal error: Call to undefined function foobar()"
// however, PHP did not "ignore" the error and terminated the
// script because the error was "fatal"

Що саме відбувається, якщо ви використовуєте користувацький обробник помилок замість стандартного обробника помилок PHP:

Якщо ви встановили спеціальну функцію обробки помилок за допомогою set_error_handler (), вона все одно буде викликатися, але цей користувальницький обробник помилок може (і повинен) викликати error_reporting (), який поверне 0, коли виклику, який викликав помилку, передував @ .

Це проілюстровано у наступному прикладі коду:

function bad_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
    echo "[bad_error_handler]: $errstr";
    return true;
}
set_error_handler("bad_error_handler");
echo @(1 / 0);
// prints "[bad_error_handler]: Division by zero"

Обробник помилок не перевірив, чи @діє символ. Посібник пропонує наступне:

function better_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
    if(error_reporting() !== 0) {
        echo "[better_error_handler]: $errstr";
    }
    // take appropriate action
    return true;
}

58

Також зауважте, що незважаючи на приховані помилки, будь-який користувальницький обробник помилок (встановлений з set_error_handler) все одно буде виконуватися!


34

Як уже дехто відповідав раніше: @Оператор пригнічує всі помилки в PHP, включаючи повідомлення, попередження та навіть критичні помилки.

АЛЕ: Будь ласка, дійсно взагалі не використовуйте @оператора.

Чому?

Ну, тому що, використовуючи @оператор для придушення помилок, у вас взагалі немає поняття, з чого почати, коли виникає помилка. У мене вже було «весело» зі застарілим кодом, де деякі розробники використовували @оператор досить часто. Особливо у таких випадках, як файлові операції, мережеві дзвінки тощо. Це все випадки, коли багато розробників рекомендують використовувати @оператора, оскільки це іноді виходить за межі, коли виникає помилка (наприклад, API 3rdparty може бути недосяжним тощо). ).

Але який сенс все одно не використовувати? Давайте подивимось з двох позицій:

Як розробник: Коли@я використовуюсь, я абсолютно не маю уявлення, з чого почати. Якщо є сотні, а то й тисячі функціональних дзвінків,@помилка може бути як і всі. У цьому випадку не можлива розумна налагодження. І навіть якщо це лише помилка третьої сторони - тоді це просто добре, і ви швидко зробите. ;-) Більше того, краще додати достатньо деталей до журналу помилок, тому розробники можуть легко вирішити, чи є запис журналу чимось, що потрібно перевірити далі чи це лише помилка 3rdparty, яка виходить за межі розробника.

Як користувач: Користувачів зовсім не цікавить, в чому причина помилки чи ні. Програмне забезпечення існує для того, щоб вони працювали, вирішували конкретне завдання тощо. Їм не байдуже, чи це вина розробника чи проблема третьої сторони. Спеціально для користувачів, я настійно рекомендую реєструвати всі помилки, навіть якщо вони виходять за межі сфери. Можливо, ви помітите, що певний API часто офлайн. Що ти можеш зробити? Ви можете поговорити зі своїм партнером API, і якщо вони не зможуть підтримувати його стабільним, вам, ймовірно, слід шукати іншого партнера.

Коротше кажучи: ви повинні знати, що існує щось на зразок @(знання завжди добре), але просто не користуйтеся цим . Багато розробників (особливо ті, що налагоджують код від інших) будуть дуже вдячні.


1
Деякі попередження можна надійно придушити лише за допомогою @ (наприклад, fopen (), де будь-яка спроба передбачити результат підлягає гоночній умові), якщо у вас є код, щоб впорядковувати стан помилки більш акуратно, то usuig @- це правильно робити, це особливо корисно, особливо якщо ви не повертаєтесь text/html(або подібне) до клієнта. (можливо повернення image/pngабо "json")
Ясен

1
Вам не слід придушувати попередження - вони стверджують, що ви зробили щось не так. Не існує гоночного стану, в якому ви не можете правильно перевірити чи обробляти стан.
Ryan Rentfro

1
У моєму коді є декілька місць. if( session_status() == PHP_SESSION_NONE ) session_start(); Це спадковий додаток, який я успадкував, і є місця, де сценарій настройки викликається кілька разів, тому мені доведеться перевірити. Яка проблема виникне у простому використанні @session_start();?
Stephen R

Якщо ви знаєте, що робите, і використовуєте це економно / стратегічно, це варто використовувати. @$this->stats['device_os'][$date][$creative_id][$device_id][$operating_system]['clicks']++;є набагато кращим, ніж альтернатива - перевірка розміщення на кожному рівні та заповнення її, коли її немає.
dtbarne

1
Дайте мені вагому причину, чому додавати 12+ рядків коду та не додавати значення, а лише знижувати читабельність та стислість коду варто робити, окрім того, що ви десь читали десь, що він "просто брудний", і, можливо, ви можете змінити свою думку.
dtbarne

7

Припустимо, ми не використовували оператора "@", тоді наш код виглядатиме так:

$fileHandle = fopen($fileName, $writeAttributes);

А що, якщо файл, який ми намагаємось відкрити, не знайдений? На ній з’явиться повідомлення про помилку.

Для придушення повідомлення про помилку ми використовуємо оператор "@", наприклад:

$fileHandle = @fopen($fileName, $writeAttributes);

Це прекрасний приклад того, чому PHP @в першу чергу має такий спосіб вирішення. Інші мови програмування мають рівномірну обробку винятків для вирішення такого роду сценарій stackoverflow.com/questions/1087365
dreftymac

@dreftymac Саме так!
Sujeet Kumar

5

Якщо відкриття не вдається, генерується помилка рівня E_WARNING. Ви можете використовувати @ для придушення цього попередження.


5

@ пригнічує повідомлення про помилки.

Він використовується в фрагментах коду, таких як:

@file_get_contents('http://www.exaple.com');

Якщо домен " http://www.exaple.com " недоступний, буде показана помилка, але @нічого не відображається.


1

PHP підтримує одного оператора управління помилками: знак at (@) . Якщо буде надано вираз у PHP, будь-які повідомлення про помилки, які можуть бути згенеровані цим виразом, ігноруються.

Якщо ви встановили спеціальну функцію обробника помилок, set_error_handler()тоді вона все одно буде викликатися, але цей користувальницький обробник помилок може (і повинен) зателефонувати, error_reporting()який повернеться, 0коли виклику, який викликав помилку, передував an @.

<?php
/* Intentional file error */
$my_file = @file ('non_existent_file') or
    die ("Failed opening file: error was '$php_errormsg'");

// this works for any expression, not just functions:
$value = @$cache[$key];
// will not issue a notice if the index $key doesn't exist.

?>

Примітка:-

1) Оператор @ -оператор працює лише над виразами.

2) Просте правило: якщо ви можете взяти значення чогось, ви можете додати його до оператора @. Наприклад, ви можете додати його до змінних, функціонувати і включати дзвінки, константи тощо. Ви не можете передбачити його до функцій або визначень класів, або умовних структур, таких як "if" та "foreach" тощо.

Увага:-

В даний час префікс оператора керування помилками "@" навіть відключить повідомлення про помилки для критичних помилок, які припиняють виконання сценарію. Крім усього іншого, це означає, що якщо ви використовуєте "@" для придушення помилок певної функції, або вона недоступна, або вона була введена неправильно, сценарій загине прямо там, не вказуючи, чому.


1

Можливо, варто додати тут декілька покажчиків при використанні @ ви повинні бути в курсі, щоб переглянути повний перегляд цієї публікації: http://mstd.eu/index.php/2016/06/30/php- швидкий вогонь-що-що-є-символ-використовується-для-в-php /

  1. Обробник помилок все ще запускається навіть із попередньо передбаченим символом @, це просто означає, що встановлено рівень помилки 0, це доведеться обробляти належним чином у користувальницькому обробці помилок.

  2. Якщо передбачити включення з @, всі помилки у файлі включення будуть встановлені на рівні помилки 0


1

@пригнічує повідомлення про помилку, передане функцією. fopenвидає помилку, коли файл не виходить. @символ змушує виконання перейти до наступного рядка, навіть якщо файл не існує. Моя пропозиція не буде використовувати це у вашому локальному середовищі, коли ви розробляєте код PHP.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.