Can I try/catch a warning?

前端 未结 11 1031
孤城傲影
孤城傲影 2020-11-22 01:04

I need to catch some warnings being thrown from some php native functions and then handle them.

Specifically:

array dns_get_record  ( string $hostnam         


        
相关标签:
11条回答
  • 2020-11-22 01:36

    Be careful with the @ operator - while it suppresses warnings it also suppresses fatal errors. I spent a lot of time debugging a problem in a system where someone had written @mysql_query( '...' ) and the problem was that mysql support was not loaded into PHP and it threw a silent fatal error. It will be safe for those things that are part of the PHP core but please use it with care.

    bob@mypc:~$ php -a
    Interactive shell
    
    php > echo @something(); // this will just silently die...
    

    No further output - good luck debugging this!

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

    This time we can see why it failed.

    0 讨论(0)
  • 2020-11-22 01:36

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

    just include above file into your script file like this

    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
    
    0 讨论(0)
  • 2020-11-22 01:37

    try checking whether it returns some boolean value then you can simply put it as a condition. I encountered this with the oci_execute(...) which was returning some violation with my unique keys.

    ex.
    oci_parse($res, "[oracle pl/sql]");
    if(oci_execute){
    ...do something
    }
    
    0 讨论(0)
  • 2020-11-22 01:38

    I would only recommend using @ to suppress warnings when it's a straight forward operation (e.g. $prop = @($high/($width - $depth)); to skip division by zero warnings). However in most cases it's better to handle.

    0 讨论(0)
  • 2020-11-22 01:39

    I wanted to try/catch a warning, but at the same time keep the usual warning/error logging (e.g. in /var/log/apache2/error.log); for which the handler has to return false. However, since the "throw new..." statement basically interrupts the execution, one then has to do the "wrap in function" trick, also discussed in:

    Is there a static way to throw exception in php

    Or, in brief:

      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: after closer inspection, it turns out it doesn't work: the "return false && throwErrorException ..." will, basically, not throw the exception, and just log in the error log; removing the "false &&" part, as in "return throwErrorException ...", will make the exception throwing work, but will then not log in the error_log... I'd still keep this posted, though, as I haven't seen this behavior documented elsewhere.

    0 讨论(0)
  • 2020-11-22 01:47

    If dns_get_record() fails, it should return FALSE, so you can suppress the warning with @ and then check the return value.

    0 讨论(0)
提交回复
热议问题