Czy Mogę spróbować / złapać Ostrzeżenie?

Muszę wyłapać Ostrzeżenia rzucane przez niektóre natywne funkcje php, a następnie je obsłużyć.

Konkretnie:

array dns_get_record  ( string $hostname  [, int $type= DNS_ANY  [, array &$authns  [, array &$addtl  ]]] )

Wyświetla ostrzeżenie, gdy zapytanie DNS nie powiedzie się.

try/catch nie działa, ponieważ ostrzeżenie nie jest wyjątkiem.

Mam teraz 2 opcje:

  1. set_error_handler wygląda na przesadę, ponieważ muszę go użyć do filtrowania każdego ostrzeżenia na stronie (czy to prawda?);

  2. Dostosuj raportowanie/wyświetlanie błędów, aby te ostrzeżenia nie są wyświetlane na ekranie, następnie sprawdź wartość zwracaną; jeśli jest to false, nie ma rekordów dla nazwy hosta.

Jaka jest najlepsza praktyka?
Author: Lightness Races in Orbit, 2009-08-07

10 answers

Set and restore error handler

Jedną z możliwości jest ustawienie własnego programu obsługi błędów przed wywołaniem i przywrócenie poprzedniego programu obsługi błędów później za pomocą restore_error_handler().

set_error_handler(function() { /* ignore errors */ });
dns_get_record();
restore_error_handler();

Możesz oprzeć się na tym pomyśle i napisać program obsługi błędów, który rejestruje błędy za Ciebie.

set_error_handler([$logger, 'onSilencedError']);
dns_get_record();
restore_error_handler();

Zamienianie błędów w wyjątki

Możesz użyć set_error_handler() i klasy ErrorException, aby zamienić wszystkie błędy php w wyjątki.

set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext) {
    // error was suppressed with the @-operator
    if (0 === error_reporting()) {
        return false;
    }

    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});

try {
    dns_get_record();
} catch (ErrorException $e) {
    // ...
}

Ważna rzecz do Uwaga Podczas używania własnego programu obsługi błędów jest to, że ominie on ustawienie error_reporting i przekaże wszystkie błędy (powiadomienia, ostrzeżenia itp.) do obsługi błędów. Możesz ustawić drugi argument set_error_handler(), Aby określić typy błędów, które chcesz otrzymywać, lub uzyskać dostęp do bieżącego ustawienia za pomocą ... = error_reporting() wewnątrz procedury obsługi błędów.

Tłumienie Ostrzeżenia

Inną możliwością jest wstrzymanie wywołania z operatorem @ i sprawdzenie zwracanej wartości dns_get_record(). But I ' d odradzaj to , ponieważ błędy / ostrzeżenia są wyzwalane, aby być obsługiwane, a nie tłumione.

 317
Author: Philippe Gerber,
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
2014-09-04 20:06:49

Rozwiązaniem, które naprawdę działa, okazało się ustawienie prostego programu obsługi błędów z parametrem E_WARNING, TAK:

set_error_handler("warning_handler", E_WARNING);
dns_get_record(...)
restore_error_handler();

function warning_handler($errno, $errstr) { 
// do something
}
 120
Author: Robert,
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
2016-03-17 11:12:40

Bądź ostrożny z operatorem @ - podczas gdy tłumi on Ostrzeżenia, tłumi również błędy krytyczne. Spędziłem dużo czasu debugując problem w systemie, w którym ktoś napisał @mysql_query( '...' ) i problem polegał na tym, że obsługa mysql nie została załadowana do PHP i wyrzuciła cichy błąd krytyczny. Będzie to bezpieczne dla tych rzeczy, które są częścią rdzenia PHP, ale proszę używać go ostrożnie.

bob@mypc:~$ php -a
Interactive shell

php > echo @something(); // this will just silently die...

Brak dalszych danych wyjściowych-powodzenia w debugowaniu tego!

bob@mypc:~$ php -a
Interactive shell

php > echo something(); // lets try it again but don't suppress the error
PHP Fatal error:  Call to undefined function something() in php shell code on line 1
PHP Stack trace:
PHP   1. {main}() php shell code:0
bob@mypc:~$ 

Tym razem widać, dlaczego się nie udało.

 26
Author: GuruBob,
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-03-30 10:31:58

Chciałem spróbować / złapać Ostrzeżenie, ale jednocześnie zachować zwykłe Ostrzeżenie / rejestrowanie błędów (np. w /var/log/apache2/error.log); dla którego handler musi zwrócić false. Jednak od " rzucać nowe..."twierdzenie zasadniczo przerywa wykonanie, następnie należy wykonać trik "zawijania funkcji", omówiony również w:

Czy istnieje statyczny sposób na wyrzucenie wyjątku w php

Lub w skrócie:

  function throwErrorException($errstr = null,$code = null, $errno = null, $errfile = null, $errline = null) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
  }
  function warning_handler($errno, $errstr, $errfile, $errline, array $errcontext) {
    return false && throwErrorException($errstr, 0, $errno, $errfile, $errline);
    # error_log("AAA"); # will never run after throw
    /* Do execute PHP internal error handler */
    # return false; # will never run after throw
  }
  ...
  set_error_handler('warning_handler', E_WARNING);
  ...
  try {
    mkdir($path, 0777, true);
  } catch (Exception $e) {
    echo $e->getMessage();
    // ...
  }

EDIT: po bliższym przyjrzeniu się okazuje się, że nie działa: the "return false && throwErrorException ... "w zasadzie Nie rzuci wyjątek i po prostu zaloguje się do dziennika błędów; usunięcie części" false &&", jak w "return throwErrorException ...", spowoduje, że rzucenie wyjątku zadziała, ale nie zaloguje się do dziennika błędów... Nadal będę to informował, ponieważ nie widziałem tego zachowania udokumentowanego gdzie indziej.

 5
Author: sdaau,
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-05-23 12:02:48

Prawdopodobnie powinieneś spróbować całkowicie pozbyć się ostrzeżenia, ale jeśli nie jest to możliwe, możesz poprzedzić wywołanie za pomocą @ (tj. @ dns_get_record (...)), a następnie użyj wszelkich informacji, które możesz uzyskać, aby dowiedzieć się, czy Ostrzeżenie stało się, czy nie.

 4
Author: rpjohnst,
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-08-06 21:53:51

Zwykle nie należy używać@, chyba że jest to jedyne rozwiązanie. W tym konkretnym przypadku należy najpierw użyć funkcji dns_check_record, aby dowiedzieć się, czy rekord istnieje.

 3
Author: florynth,
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
2011-01-03 22:23:24

Jeśli dns_get_record() nie powiedzie się, powinien zwrócić FALSE, aby można było wyłączyć ostrzeżenie za pomocą @, a następnie sprawdzić wartość zwracaną.

 2
Author: Amber,
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-08-06 21:58:19

Połączenie tych linii kodu wokół wywołania file_get_contents() do zewnętrznego adresu url pomogło mi obsłużyć Ostrzeżenia typu "failed to open stream: Connection timed out " znacznie lepiej:

set_error_handler(function ($err_severity, $err_msg, $err_file, $err_line, array $err_context)
{
    throw new ErrorException( $err_msg, 0, $err_severity, $err_file, $err_line );
}, E_WARNING);
try {
    $iResult = file_get_contents($sUrl);
} catch (Exception $e) {
    $this->sErrorMsg = $e->getMessage();
}
restore_error_handler();

To rozwiązanie działa również w kontekście obiektu. Można go użyć w funkcji:

public function myContentGetter($sUrl)
{
  ... code above ...
  return $iResult;
}
 1
Author: Bugfighter,
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
2018-06-28 21:30:43

Spróbuj sprawdzić, czy zwraca jakąś wartość logiczną, a następnie możesz ją po prostu umieścić jako warunek. Natknąłem się na to z oci_execute(...), który zwrócił jakieś naruszenie z moich unikalnych kluczy.

ex.
oci_parse($res, "[oracle pl/sql]");
if(oci_execute){
...do something
}
 0
Author: gborjal,
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-11-08 02:07:26

Polecam tylko użycie @ do tłumienia ostrzeżeń, gdy jest to prosta operacja (np. $prop = @($high / ($width - $depth)); aby pominąć dzielenie przez zero ostrzeżeń). Jednak w większości przypadków lepiej sobie z tym poradzić.

 -2
Author: tanovellino,
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-08-14 07:46:05