it-swarm.com.de

Kann ich eine Warnung versuchen/fangen?

Ich muss einige Warnungen aus ein paar php-nativen Funktionen abfangen und dann behandeln.

Speziell:

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

Es wird eine Warnung ausgegeben, wenn die DNS-Abfrage fehlschlägt.

try/catch funktioniert nicht, da eine Warnung keine Ausnahme ist.

Ich habe jetzt 2 Möglichkeiten:

  1. set_error_handler scheint wie übertrieben zu sein, da ich jede Warnung auf der Seite filtern muss (ist das wahr?);

  2. Passen Sie die Fehlermeldung/Anzeige so an, dass diese Warnungen nicht auf dem Bildschirm angezeigt werden, und überprüfen Sie den Rückgabewert. Bei false werden keine Einträge für den Hostnamen gefunden.

Was ist die beste Praxis hier?

307
user121196

Fehlerbehandlung setzen und wiederherstellen

Eine Möglichkeit besteht darin, vor dem Aufruf einen eigenen Fehlerhandler festzulegen und den vorherigen Fehlerhandler später mit restore_error_handler() wiederherzustellen.

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

Sie könnten auf dieser Idee aufbauen und einen wiederverwendbaren Fehlerbehandler schreiben, der die Fehler für Sie protokolliert.

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

Aus Fehlern Fehler machen

Sie können set_error_handler() und die Klasse ErrorException verwenden, um alle PHP-Fehler in Ausnahmen zu konvertieren.

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) {
    // ...
}

Beachten Sie bei der Verwendung Ihres eigenen Fehlerhandlers, dass die Einstellung error_reporting umgangen wird und alle Fehler (Hinweise, Warnungen usw.) an Ihren Fehlerhandler weitergegeben werden. Sie können ein zweites Argument für set_error_handler() angeben, um festzulegen, welche Fehlertypen Sie erhalten möchten, oder auf die aktuelle Einstellung mit ... = error_reporting() im Fehlerbehandlungsprogramm zugreifen.

Unterdrückung der Warnung

Eine andere Möglichkeit ist, den Aufruf mit dem Operator @ zu unterdrücken und anschließend den Rückgabewert von dns_get_record() zu überprüfen. Aber ich würde davon abraten da Fehler/Warnungen ausgelöst werden, um gehandhabt zu werden, nicht unterdrückt zu werden.

332
Philippe Gerber

Die wirklich funktionierende Lösung stellte sich als einfache Fehlerbehandlung mit dem E_WARNING-Parameter heraus.

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

function warning_handler($errno, $errstr) { 
// do something
}
126
Robert

Seien Sie vorsichtig mit dem @-Operator - und unterdrückt Warnungen sowie schwerwiegende Fehler. Ich verbrachte viel Zeit damit, ein Problem in einem System zu debuggen, in dem jemand @mysql_query( '...' ) geschrieben hatte, und das Problem bestand darin, dass die Mysql-Unterstützung nicht in PHP geladen war und es zu einem stillen fatalen Fehler kam. Es ist sicher für die Dinge, die Teil des PHP -Kerns sind, aber please verwenden Sie es mit Bedacht.

[email protected]:~$ php -a
Interactive Shell

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

Keine weiteren Ausgaben - viel Erfolg beim Debuggen!

[email protected]:~$ 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
[email protected]:~$ 

Dieses Mal können wir sehen, warum es fehlgeschlagen ist.

27
GuruBob

Ich wollte eine Warnung versuchen/abfangen, gleichzeitig jedoch die üblichen Warn-/Fehlerprotokolle beibehalten (z. B. in /var/log/Apache2/error.log). für die der Handler false zurückgeben muss. Da jedoch die Anweisung "Neue werfen ..." im Wesentlichen die Ausführung unterbricht, muss der Trick "Wrap in function" ausgeführt werden. 

Gibt es eine statische Möglichkeit, eine Ausnahme in php auszulösen

Oder kurz:

  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();
    // ...
  }

BEARBEITEN: Nach näherer Betrachtung stellt sich heraus, dass es nicht funktioniert: Der "return false && throwErrorException ..." wird im Grunde nicht die Ausnahme auslösen und sich einfach im Fehlerprotokoll anmelden. Wenn Sie den Teil "false &&" entfernen (wie in "return throwErrorException ..."), wird die Ausnahme zwar ausgelöst, aber dann wird kein Fehler im Protokoll protokolliert. Ich würde dies jedoch weiterhin auf dem Laufenden halten, da dieses Verhalten nicht dokumentiert wurde anderswo.

5
sdaau

Sie sollten wahrscheinlich versuchen, die Warnung vollständig zu entfernen, aber wenn dies nicht möglich ist, können Sie den Anruf mit @ (dh @dns_get_record (...)) voranstellen und dann alle Informationen verwenden, die Sie erhalten, um herauszufinden, ob die Warnung aufgetreten ist oder nicht.

4
rpjohnst

Das Kombinieren dieser Codezeilen um einen file_get_contents()-Aufruf zu einer externen URL hat mir geholfen, Warnungen wie " fehlgeschlagen, um den Stream zu öffnen: Verbindung mit Zeitüberschreitung " viel besser:

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();

Diese Lösung funktioniert auch im Objektkontext. Sie könnten es in einer Funktion verwenden:

public function myContentGetter($sUrl)
{
  ... code above ...
  return $iResult;
}
3
Bugfighter

Normalerweise sollten Sie @ nicht verwenden, es sei denn, dies ist die einzige Lösung. In diesem speziellen Fall sollte zuerst die Funktion dns_check_record verwendet werden, um festzustellen, ob der Datensatz vorhanden ist.

3
florynth

Wenn dns_get_record() fehlschlägt, sollte FALSE zurückgegeben werden, sodass Sie die Warnung mit @ unterdrücken und den Rückgabewert überprüfen können.

2
Amber

versuchen Sie zu prüfen, ob ein boolescher Wert zurückgegeben wird. Dann können Sie ihn einfach als Bedingung angeben. Dies ist mir beim oci_execute (...) aufgefallen, das mit meinen eindeutigen Schlüsseln zu Verletzungen geführt hat.

ex.
oci_parse($res, "[Oracle pl/sql]");
if(oci_execute){
...do something
}
0
gborjal