Frage

Ich brauche ein paar Warnungen fangen von einigen PHP-native Funktionen geworfen wurde und dann mit ihnen umgehen.

Im Einzelnen:

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

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

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

Ich habe jetzt 2 Möglichkeiten:

  1. set_error_handler scheint übertrieben, weil ich es benutzen jede Warnung in der Seite zu filtern (ist das wahr?);

  2. Fehlermeldungen / Display so einstellen, haben diese Warnungen nicht auf Bildschirm angezeigt bekommen, dann überprüfen Sie den Rückgabewert; wenn es false ist, wird keine Datensätze für die Hostnamen gefunden.

Was ist die beste Praxis hier?

War es hilfreich?

Lösung

Set und wiederherstellen Fehlerbehandlung

Eine Möglichkeit ist, Ihre eigene Fehlerbehandlung vor dem Aufruf zu setzen und die vorherigen Fehler-Handler später mit restore_error_handler() wiederherstellen.

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

Sie können auf dieser Idee bauen und ein wiederverwendbares Fehlerhandler schreiben, die die Fehler für Sie protokolliert.

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

Turning Fehler in Ausnahmen

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

set_error_handler(function($errno, $errstr, $errfile, $errline, $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) {
    // ...
}

Die wichtige Sache zu beachten, wenn die eigene Fehlerbehandlung ist, dass es die error_reporting Einstellung umgehen und alle Fehler passieren (Hinweise, Warnungen, etc.), um Ihre Fehlerbehandlungsroutine. Sie können ein zweites Argument auf set_error_handler() gesetzt zu definieren, welche Fehlertypen, die Sie empfangen möchten, oder die aktuelle Einstellung Zugriff ... = error_reporting() innerhalb der Fehlerbehandlung verwendet wird.

Unterdrücken der Warnung

Eine andere Möglichkeit ist das Gespräch mit dem Operator @ zu unterdrücken und den Rückgabewert von dns_get_record() danach überprüfen. Aber ich würde davon abraten, diese als Fehler / Warnungen ausgelöst werden, behandelt werden, nicht unterdrückt werden.

Andere Tipps

Die Lösung, die einfache Fehlerbehandlung mit E_WARNING Parametern seiner Einstellung klappt wirklich eingeschaltet, etwa so:

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

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

Seien Sie vorsichtig mit dem @ Operator - während es Warnungen unterdrückt es unterdrückt auch fatale Fehler. Ich verbrachte viel Zeit, um ein Problem in einem System debuggen, wo jemand @mysql_query( '...' ) geschrieben hatte und das Problem war, dass MySQL-Unterstützung nicht in PHP geladen wurde und es warf einen stillen fatalen Fehler. Es wird für diese Dinge sicher sein, dass ein Teil des PHP-Kern sind aber Sie verwenden Sie es mit Vorsicht.

bob@mypc:~$ php -a
Interactive shell

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

Keine weiteren Ausgang - viel Glück Debuggen dieses

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:~$ 

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

wollte ich versuchen, / eine Warnung fangen, aber zugleich halte die übliche Warnung / Fehlerprotokollierung (z.B. in /var/log/apache2/error.log); für die der Handler false zurückzukehren. Da jedoch die „neue werfen ...“ Anweisung im Grunde die Ausführung unterbricht, hat man dann den „wrap in Funktion“ Trick zu tun, auch diskutiert in:

Gibt es eine statische Art und Weise Ausnahme in php zu werfen

Oder, kurz gesagt:

  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: nach näherer Betrachtung stellt sich heraus, es funktioniert nicht: Die „return false && throwErrorException ...“ wird, im Grunde genommen, nicht werfen die Ausnahme, und melden Sie sich nur im Fehlerprotokoll; den „false &&“ Teil zu entfernen, wie in „return throwErrorException ...“, wird die Ausnahme wirft Arbeit machen, aber dann in der error_log nicht anmelden ... Ich werde noch halte diese geschrieben, aber, wie ich dieses Verhalten nicht gesehen habe dokumentiert an anderer Stelle.

Sie sollten wahrscheinlich versuchen, die Warnung vollständig loszuwerden, aber wenn das nicht möglich ist, können Sie den Anruf mit @ (dh @dns_get_record (...)) voranstellen und dann keine Informationen verwenden, können Sie bekommen, um herauszufinden, ob die Warnung passiert ist oder nicht.

Normalerweise sollten Sie nie @ verwenden, wenn dies die einzige Lösung ist. In diesem speziellen Fall sollte die Funktion dns_check_record zuerst verwenden werden, um zu wissen, ob der Datensatz vorhanden ist.

Die Kombination dieser Zeilen Code um einen file_get_contents() Anruf an eine externe URL half mir Warnungen behandeln wie " failed to open stream: Connection timed out " 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 im Objektkontext auch. Man kann es in einer Funktion verwenden:

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

Wenn dns_get_record() ausfällt, sollte es FALSE zurückkehren, so dass Sie die Warnung mit @ unterdrücken kann, und überprüfen Sie den Rückgabewert.

versuchen zu überprüfen, ob es etwas boolean Wert zurückgibt, dann können Sie ihn einfach als einen Zustand versetzt. Ich traf dies mit dem oci_execute (...), die eine Verletzung mit meinem einzigartigen Schlüssel zurückkehrt.

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

FolderStructure

index.php //Script File
logs //Folder for log Every warning and Errors
CustomException.php //Custom exception File

CustomException.php

/**
* Custom error handler
*/
function handleError($code, $description, $file = null, $line = null, $context = null) {
    $displayErrors = ini_get("display_errors");;
    $displayErrors = strtolower($displayErrors);
    if (error_reporting() === 0 || $displayErrors === "on") {
        return false;
    }
    list($error, $log) = mapErrorCode($code);
    $data = array(
        'timestamp' => date("Y-m-d H:i:s:u", time()),
        'level' => $log,
        'code' => $code,
        'type' => $error,
        'description' => $description,
        'file' => $file,
        'line' => $line,
        'context' => $context,
        'path' => $file,
        'message' => $error . ' (' . $code . '): ' . $description . ' in [' . $file . ', line ' . $line . ']'
    );
    $data = array_map('htmlentities',$data);
    return fileLog(json_encode($data));
}

/**
* This method is used to write data in file
* @param mixed $logData
* @param string $fileName
* @return boolean
*/
function fileLog($logData, $fileName = ERROR_LOG_FILE) {
    $fh = fopen($fileName, 'a+');
    if (is_array($logData)) {
        $logData = print_r($logData, 1);
    }
    $status = fwrite($fh, $logData . "\n");
    fclose($fh);
//    $file = file_get_contents($filename);
//    $content = '[' . $file .']';
//    file_put_contents($content); 
    return ($status) ? true : false;
}

/**
* Map an error code into an Error word, and log location.
*
* @param int $code Error code to map
* @return array Array of error word, and log location.
*/
function mapErrorCode($code) {
    $error = $log = null;
    switch ($code) {
        case E_PARSE:
        case E_ERROR:
        case E_CORE_ERROR:
        case E_COMPILE_ERROR:
        case E_USER_ERROR:
            $error = 'Fatal Error';
            $log = LOG_ERR;
            break;
        case E_WARNING:
        case E_USER_WARNING:
        case E_COMPILE_WARNING:
        case E_RECOVERABLE_ERROR:
            $error = 'Warning';
            $log = LOG_WARNING;
            break;
        case E_NOTICE:
        case E_USER_NOTICE:
            $error = 'Notice';
            $log = LOG_NOTICE;
            break;
        case E_STRICT:
            $error = 'Strict';
            $log = LOG_NOTICE;
            break;
        case E_DEPRECATED:
        case E_USER_DEPRECATED:
            $error = 'Deprecated';
            $log = LOG_NOTICE;
            break;
        default :
            break;
    }
    return array($error, $log);
}
//calling custom error handler
set_error_handler("handleError");

nur schließen oben Datei in die Skript-Datei wie folgt

index.php

error_reporting(E_ALL);
ini_set('display_errors', 'off');
define('ERROR_LOG_FILE', 'logs/app_errors.log');

include_once 'CustomException.php';
echo $a; // here undefined variable warning will be logged into logs/app_errors.log

Ich würde nur mit @ empfehlen Warnungen zu unterdrücken, wenn es sich um ein gerade Vorwärtsbetrieb ist (zum Beispiel $ prop = @ ($ hoch / (Breite $ - $ Tiefe)); überspringen Division durch Null Warnungen). Doch in den meisten Fällen ist es besser zu handhaben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top