Eliminuje błąd z operatorem @ w PHP

Twoim zdaniem, czy użycie operatora @ do tłumienia błędu/ostrzeżenia w PHP jest słuszne, podczas gdy ty możesz obsługiwać błąd?

Jeśli tak, to w jakich okolicznościach użyłbyś tego?

Przykłady kodu są mile widziane.

Edit: Uwaga do repliers. Nie chcę wyłączać zgłaszania błędów, ale na przykład powszechną praktyką jest używanie

@fopen($file);

A potem sprawdź... ale możesz się pozbyć @ robiąc

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

Lub podobne.

Wydaje mi się, że pytanie brzmi - czy jest gdzieś, że @ musi być używany, aby stłumić błąd, który nie może być obsługiwany w żaden inny sposób?

Author: VolkerK, 2008-09-25

16 answers

Usunąłbym błąd i zajął się nim . W przeciwnym razie możesz mieć toctou issue (Time-of-check, time-of-use. Na przykład plik może zostać usunięty po tym, jak file_exists zwróci true, ale przed fopen).

Ale nie ukrywam błędów, żeby je usunąć. Lepiej, żeby były widoczne.

 26
Author: Paweł Hajdan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-12 14:48:45

Uwaga: Po pierwsze, zdaję sobie sprawę, że 99% programistów PHP używa operatora tłumienia błędów( kiedyś byłem jednym z nich), więc oczekuję, że każdy programista PHP, który to widzi, nie zgodzi się.

Twoim zdaniem, czy jest ważne użycie operatora @ do tłumienia błędu/ostrzeżenia w PHP, podczas gdy możesz obsługiwać błąd?

Krótka odpowiedź:
Nie!

Więcej poprawnej odpowiedzi:
Nie wiem jak Nie wiem wszystkiego, ale do tej pory nie doszedłem w sytuacji, w której było to dobre rozwiązanie.

Dlaczego jest źle:
W tym, co myślę, że jest około 7 lat za pomocą PHP teraz widziałem niekończące się agonii debugowania spowodowane przez operatora tłumienia błędów i nigdy nie spotkałem się z sytuacją, w której było to nieuniknione.

Problem polega na tym, że fragment kodu, dla którego tłumisz błędy, może obecnie powodować tylko ten błąd, który widzisz; jednak gdy zmienisz kod, na którym opiera się tłumiona linia, lub środowisko w którym działa, wtedy jest szansa, że linia będzie próbowała wyprowadzić zupełnie inny błąd niż ten, który próbowałeś zignorować. Więc jak wyśledzić błąd, który nie wychodzi? Witamy w debugging hell!

Wiele lat zajęło mi uświadomienie sobie, ile czasu traciłem co kilka miesięcy z powodu tłumionych błędów. Najczęściej (ale nie wyłącznie) było to po zainstalowaniu zewnętrznego skryptu / aplikacji/biblioteki, która była wolna od błędów u programistów środowiska, ale nie Mojego z powodu różnicy w konfiguracji php lub serwera lub brakującej zależności, która normalnie generowałaby błąd natychmiast ostrzegający o problemie, ale nie wtedy, gdy dev dodaje magic @.

Alternatywy (w zależności od sytuacji i pożądanego rezultatu):
Obsłużyć rzeczywisty błąd, który jesteś świadomy, tak, że jeśli kawałek kodu ma spowodować pewien błąd, to nie jest uruchamiany w tej konkretnej sytuacji. Ale myślę, że rozumiesz to. część i po prostu martwiłeś się, że użytkownicy końcowi widzą błędy, co teraz zajmę się.

W przypadku zwykłych błędów możesz skonfigurować obsługę błędów, aby były wyświetlane w sposób, w jaki chcesz, gdy przeglądasz stronę, ale ukryte przed użytkownikami końcowymi i zalogowane, abyś wiedział, jakie błędy wyzwalają Twoi użytkownicy.

Dla błędów krytycznych Ustaw display_errors Na off (Twój program obsługi błędów zostanie uruchomiony) w php.ini i Włącz rejestrowanie błędów. Jeśli posiadasz również serwer deweloperski jako serwer na żywo (który polecam) ten krok nie jest konieczny na serwerze deweloperskim, więc nadal możesz debugować te krytyczne błędy bez konieczności uciekania się do patrzenia na plik dziennika błędów. Istnieje nawet sztuczka wykorzystująca funkcję zamykania , Aby wysłać wiele błędów krytycznych do obsługi błędów.

W skrócie:
Proszę, unikaj tego. Może być ku temu dobry powód, ale jeszcze go nie widzę, więc do tego dnia moim zdaniem tłumienie błędów ( @ ) operator jest zły.

Możesz przeczytać mój komentarz na stronie operatory kontroli błędów w podręczniku PHP, jeśli chcesz więcej informacji.

 120
Author: Gerry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-11 06:25:26

Tak tłumienie ma sens.

Na przykład, polecenie fopen() zwraca FALSE, jeśli nie można otworzyć pliku. W porządku, ale to również tworzy komunikat ostrzegawczy PHP. Często nie chcesz Ostrzeżenia-sam sprawdź FALSE.

W rzeczywistości podręcznik PHP szczególnie sugeruje użycie @ w tym przypadku!

 20
Author: Jason Cohen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-25 23:39:33

Jeśli nie chcesz, aby Ostrzeżenie rzucane podczas korzystania z funkcji takich jak fopen (), możesz stłumić błąd, ale użyj WYJĄTKÓW:

try {
    if (($fp = @fopen($filename, "r")) == false) {
        throw new Exception;
    } else {
        do_file_stuff();
    }
} catch (Exception $e) {
    handle_exception();
}
 13
Author: dirtside,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 04:07:41

Nigdy nie pozwalam sobie na użycie '@'... kropka.

Kiedy odkrywam użycie ' @ ' w kodzie, dodaję komentarze, aby było to wyraźnie widoczne, zarówno w punkcie użycia, jak i w blokadzie dokumentów wokół funkcji, w której jest używana. Ja też zostałem ugryziony przez debugowanie "goni ducha" z powodu tego rodzaju tłumienia błędów i mam nadzieję, że ułatwi to następnej osobie, podkreślając jej użycie, gdy go znajdę.

W przypadkach, gdy chcę, aby mój własny kod rzucił wyjątek, jeśli rodzimy Funkcja PHP napotyka błąd, a '@' wydaje się być łatwym sposobem, zamiast tego wybieram coś innego, co uzyskuje ten sam wynik, ale jest (ponownie) wyraźnie widoczne w kodzie:

$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'); }

To o wiele więcej kodu, który po prostu pisze:

$result = @native_func();
[2]}ale wolę, aby moje tłumienie było bardzo oczywiste, ze względu na biedną duszę debugowania, która za mną podąża.
 7
Author: ashnazg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-15 20:51:08

Należy unikać tłumienia błędów, chyba że wiesz możesz poradzić sobie ze wszystkimi warunkami.

To może być o wiele trudniejsze niż się wydaje na początku.

To, co naprawdę powinieneś zrobić, to polegać na "error_log" php, aby być metodą raportowania, ponieważ nie możesz polegać na użytkownikach przeglądających strony, aby zgłaszać błędy. ( I powinieneś również wyłączyć php z wyświetlania tych błędów )

Wtedy przynajmniej będziesz miał kompleksowy raport o wszystkim, co dzieje się źle w systemie.

Jeśli naprawdę musisz obsłużyć błędy, możesz utworzyć niestandardową obsługę błędów

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

Wtedy możesz wysłać wyjątki ( które mogą być obsługiwane ) i zrobić wszystko, co potrzebne, aby zgłosić dziwne błędy administracji.

 6
Author: Kent Fredric,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-25 23:51:46

Większość ludzi nie rozumie znaczenia Komunikatu o błędzie.
Nie żartuj. Większość z nich.

Myślą, że komunikaty o błędach są takie same, mówią: "coś idzie nie tak!"
Nie chcą tego czytać.
Chociaż jest to najważniejsza część komunikatu o błędzie - nie tylko fakt, że został podniesiony, ale jego znaczenie. Może Ci powiedzieć co idzie źle. Komunikaty o błędach służą do pomocy, a nie do zawracania ci głowy "jak to ukryć?"problem. To jeden z największych nieporozumienia w świecie newbie web-programming.

Tak więc, zamiast zakneblować komunikat o błędzie, należy przeczytać co on mówi. Ma nie tylko jedną wartość "file not found". Mogą być tysiące różnych błędów: permission denied, save mode restriction, open_basedir restriction itd.itd. Każdy z nich wymaga odpowiednich działań. Ale jeśli to zakneblujesz, nigdy się nie dowiesz, co się stało!

OP namiesza błąd raportowanie z błędem obsługa , podczas gdy jest bardzo duży różnica!
Obsługa błędów jest dla użytkownika. "coś się stało" wystarczy.
Podczas gdy raportowanie błędów jest dla programistów, którzy desperacko muszą wiedzieć, co z pewnością się stało.

Dlatego nigdy nie knebluj komunikatów o błędach. Zarówno loguje to dla programisty, jak i obsługuje to dla użytkownika.

 5
Author: Your Common Sense,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-06 08:31:28

Czy nie ma sposobu na wyłączenie z php.ostrzeżenia i błędy ini? w takim przypadku możesz debugować tylko zmieniając flagę i nie próbując odkrywać, który @ ukrywa problem.

 3
Author: Enrico Murru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-25 23:45:49

Używanie @ jest czasami przeciwne do zamierzonego. Z mojego doświadczenia wynika, że zawsze powinieneś wyłączyć raportowanie błędów w php.ini lub call

error_reporting(0);

W zakładzie produkcyjnym. W ten sposób, gdy jesteś w fazie rozwoju, możesz po prostu skomentować linię i zachować błędy widoczne dla debugowania.

 3
Author: Eric Lamb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 00:03:14

Jedno miejsce, którego używam, znajduje się w kodzie gniazda, na przykład, jeśli masz ustawiony limit czasu, otrzymasz ostrzeżenie o tym, jeśli nie dodasz@, nawet jeśli ważne jest, aby nie dostać pakietu.

$data_len = @socket_recvfrom( $sock, $buffer, 512, 0, $remote_host, $remote_port )
 3
Author: Don Neufeld,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-26 01:22:50

Jedynym miejscem, gdzie naprawdę potrzebowałem jej użyć, jest funkcja eval. Problem z eval polega na tym, że gdy string nie może być parsowany z powodu błędu składni, eval nie zwraca false, ale raczej wyrzuca błąd, tak jak błąd parsowania w zwykłym skrypcie. Aby sprawdzić, czy skrypt zapisany w łańcuchu jest przetwarzalny, możesz użyć czegoś w stylu:

$script_ok = @eval('return true; '.$script);
AFAIK, to najbardziej elegancki sposób.
 3
Author: Milan Babuškov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-21 00:12:16

Niektóre funkcje w PHP wydadzą E_NOTICE (na przykład funkcja unserialize ).

Możliwym sposobem na wychwycenie tego błędu (dla PHP w wersji 7+) jest przekonwertowanie wszystkich wydanych błędów na wyjątki i nie pozwól, aby wydało E_NOTICE. Możemy zmienić obsługę błędu wyjątku w następujący sposób:

function exception_error_handler($severity, $message, $file, $line) {                                                                       
    throw new ErrorException($message, 0, $severity, $file, $line);          
}                                                                            

set_error_handler('exception_error_handler');                          

try {             
    unserialize('foo');
} catch(\Exception $e) {
    // ... will throw the exception here
}       
 2
Author: Daan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-27 13:04:32

Nie chcesz tłumić wszystkiego, ponieważ spowalnia to twój scenariusz.

I tak jest sposób zarówno w php.ini i wewnątrz skryptu, aby usunąć błędy (ale zrobić to tylko wtedy, gdy jesteś w środowisku na żywo i rejestrować swoje błędy z php)

<?php
    error_reporting(0);
?>

I możesz przeczytać to dla php.wersja ini wyłączania.

 1
Author: Ólafur Waage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-25 23:48:30

Dzisiaj natknąłem się na problem, który był dobrym przykładem na to, kiedy można użyć przynajmniej tymczasowo operatora@.

Długa historia w skrócie, znalazłem informacje logowania (Nazwa użytkownika i hasło w zwykłym tekście) zapisane w śledzeniu dziennika błędów.

Tutaj trochę więcej informacji na ten temat.

Logika logowania jest klasą własną, ponieważ system ma oferować różne mechanizmy logowania. Z powodu problemów z migracją serwera wystąpił błąd. Ten błąd wrzucił cały ślad do dziennika błędów, w tym informacje o Hasle! Jedna z metod oczekiwała nazwy użytkownika i hasła jako parametrów, dlatego trace zapisał wszystko wiernie do dziennika błędów.

Długoterminową poprawką jest refaktorowanie tej klasy, zamiast używania nazwy użytkownika i hasła jako 2 parametrów, na przykład używając pojedynczego parametru tablicy zawierającego te 2 wartości(trace w takich przypadkach wypisuje tablicę dla parametru). Istnieją również inne sposoby rozwiązania tego problemu, ale że to zupełnie inna sprawa.

W każdym razie. Wiadomości śledzenia są pomocne, ale w tym przypadku były wręcz szkodliwe.

Lekcja, której się nauczyłem, gdy tylko zauważyłem, że Trace output: czasami tłumienie Komunikatu o błędzie na razie jest użyteczną miarą przerwy stop, aby uniknąć dalszych szkód.

Moim zdaniem nie jest to przypadek złej konstrukcji klasowej. Sam błąd został wywołany przez PDOException (problem z znacznikiem czasu przenoszący się z MySQL 5.6 Do 5.7), który właśnie został wyrzucony przez PHP domyślnie Wszystko w dzienniku błędów.

Ogólnie nie używam operatora @ ze wszystkich powodów wyjaśnionych w innych komentarzach, ale w tym przypadku dziennik błędów przekonał mnie do zrobienia czegoś szybko, dopóki problem nie zostanie prawidłowo rozwiązany.

 1
Author: Herbert Peters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-13 06:25:23

Jeśli używasz niestandardowej funkcji obsługi błędów i chcesz stłumić błąd( prawdopodobnie znany błąd), użyj tej metody. Użycie ' @ ' nie jest dobrym pomysłem w tym kontekście, ponieważ nie powstrzyma błędu, jeśli ustawiona jest obsługa błędów.

Napisz 3 Funkcje i wywołaj w ten sposób.

# 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
}
 0
Author: Sumesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-17 01:48:00

Używam go podczas próby załadowania pliku HTML do przetworzenia jako obiektu DOMDocument. Jeśli są jakieś problemy w HTML... a jaka strona nie ma przynajmniej jednej ... DOMDocument->loadHTMLFile() wyświetli błąd, jeśli nie stłumisz go za pomocą @. Tylko w ten sposób (być może są lepsze) udało mi się stworzyć skrobaki HTML w PHP.

 -1
Author: Steve Paulo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-25 23:52:48