• 捕获php中的错误与异常


    关于配置

    1、display_errors

    ; This directive controls whether or not and where PHP will output errors,
    ; notices and warnings too. Error output is very useful during development, but
    ; it could be very dangerous in production environments. Depending on the code
    ; which is triggering the error, sensitive information could potentially leak
    ; out of your application such as database usernames and passwords or worse.
    ; For production environments, we recommend logging errors rather than
    ; sending them to STDOUT.
    ; Possible Values:
    ;   Off = Do not display any errors
    ;   stderr = Display errors to STDERR (affects only CGI/CLI binaries!)
    ;   On or stdout = Display errors to STDOUT
    ; Default Value: On
    ; Development Value: On
    ; Production Value: Off
    ; http://php.net/display-errors
    display_errors = Off
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    此配置会将errors,notices,warnings类型的信息发送给标准输出STDOUT,也就是会打印出错误信息,建议开发环境设置为On,正式环境设置为Off

    运行时设置ini_set('display_errors', TRUE);

    2、error_reporting

    ; This directive informs PHP of which errors, warnings and notices you would like
    ; it to take action for. The recommended way of setting values for this
    ; directive is through the use of the error level constants and bitwise
    ; operators. The error level constants are below here for convenience as well as
    ; some common settings and their meanings.
    ; By default, PHP is set to take action on all errors, notices and warnings EXCEPT
    ; those related to E_NOTICE and E_STRICT, which together cover best practices and
    ; recommended coding standards in PHP. For performance reasons, this is the
    ; recommend error reporting setting. Your production server shouldn't be wasting
    ; resources complaining about best practices and coding standards. That's what
    ; development servers and development settings are for.
    ; Note: The php.ini-development file has this setting as E_ALL. This
    ; means it pretty much reports everything which is exactly what you want during
    ; development and early testing.
    ;
    ; Error Level Constants:
    ; E_ALL             - All errors and warnings (includes E_STRICT as of PHP 5.4.0)
    ; E_ERROR           - fatal run-time errors
    ; E_RECOVERABLE_ERROR  - almost fatal run-time errors
    ; E_WARNING         - run-time warnings (non-fatal errors)
    ; E_PARSE           - compile-time parse errors
    ; E_NOTICE          - run-time notices (these are warnings which often result
    ;                     from a bug in your code, but it's possible that it was
    ;                     intentional (e.g., using an uninitialized variable and
    ;                     relying on the fact it is automatically initialized to an
    ;                     empty string)
    ; E_STRICT          - run-time notices, enable to have PHP suggest changes
    ;                     to your code which will ensure the best interoperability
    ;                     and forward compatibility of your code
    ; E_CORE_ERROR      - fatal errors that occur during PHP's initial startup
    ; E_CORE_WARNING    - warnings (non-fatal errors) that occur during PHP's
    ;                     initial startup
    ; E_COMPILE_ERROR   - fatal compile-time errors
    ; E_COMPILE_WARNING - compile-time warnings (non-fatal errors)
    ; E_USER_ERROR      - user-generated error message
    ; E_USER_WARNING    - user-generated warning message
    ; E_USER_NOTICE     - user-generated notice message
    ; E_DEPRECATED      - warn about code that will not work in future versions
    ;                     of PHP
    ; E_USER_DEPRECATED - user-generated deprecation warnings
    ;
    ; Common Values:
    ;   E_ALL (Show all errors, warnings and notices including coding standards.)
    ;   E_ALL & ~E_NOTICE  (Show all errors, except for notices)
    ;   E_ALL & ~E_NOTICE & ~E_STRICT  (Show all errors, except for notices and coding standards warnings.)
    ;   E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR  (Show only errors)
    ; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
    ; Development Value: E_ALL
    ; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
    ; http://php.net/error-reporting
    
    error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    此配置是报告哪些错误类型。默认值为E_ALL & ~E_DEPRECATED & ~E_STRICT

    其中E_ALL & ~E_NOTICE 等价于 E_ALL ^E_NOTICE,意为报告所有信息,除了E_NOTICE类型。

    运行时设置error_reporting(E_ALL ^E_NOTICE);

    返回当前的报告级别 error_reporting();

    错误码类型:

    常量说明备注
    1E_ERROR (int)致命的运行时错误。这类错误一般是不可恢复的情况,例如内存分配导致的问题。后果是导致脚本终止不再继续运行。
    2E_WARNING (int)运行时警告 (非致命错误)。仅给出提示信息,但是脚本不会终止运行。
    4E_PARSE (int)编译时语法解析错误。解析错误仅仅由分析器产生。
    8E_NOTICE (int)运行时通知。表示脚本遇到可能会表现为错误的情况,但是在可以正常运行的脚本里面也可能会有类似的通知。
    16E_CORE_ERROR (int)在 PHP 初始化启动过程中发生的致命错误。该错误类似 E_ERROR,但是是由 PHP 引擎核心产生的。
    32E_CORE_WARNING (int)PHP 初始化启动过程中发生的警告 (非致命错误) 。类似 E_WARNING,但是是由 PHP 引擎核心产生的。
    64E_COMPILE_ERROR (int)致命编译时错误。类似 E_ERROR,但是是由 Zend 脚本引擎产生的。
    128E_COMPILE_WARNING (int)编译时警告 (非致命错误)。类似 E_WARNING,但是是由 Zend 脚本引擎产生的。
    256E_USER_ERROR (int)用户产生的错误信息。类似 E_ERROR,但是是由用户自己在代码中使用 PHP 函数 trigger_error()来产生的。
    512E_USER_WARNING (int)用户产生的警告信息。类似 E_WARNING,但是是由用户自己在代码中使用 PHP 函数 trigger_error()来产生的。
    1024E_USER_NOTICE (int)用户产生的通知信息。类似 E_NOTICE,但是是由用户自己在代码中使用 PHP 函数 trigger_error()来产生的。
    2048E_STRICT (int)启用 PHP 对代码的修改建议,以确保代码具有最佳的互操作性和向前兼容性。PHP 5.4.0 之前的版本中不包含 E_ALL
    4096E_RECOVERABLE_ERROR (int)可被捕捉的致命错误。 它表示发生了一个可能非常危险的错误,但是还没有导致PHP引擎处于不稳定的状态。 如果该错误没有被用户自定义句柄捕获 (参见 set_error_handler()),将成为一个 E_ERROR 从而脚本会终止运行。自 PHP 5.2.0 起
    8192E_DEPRECATED (int)运行时通知。启用后将会对在未来版本中可能无法正常工作的代码给出警告。自 PHP 5.3.0 起
    16384E_USER_DEPRECATED (int)用户产生的警告信息。 类似 E_DEPRECATED, 但是是由用户自己在代码中使用PHP函数 trigger_error()来产生的。自 PHP 5.3.0 起
    32767E_ALL (int)PHP 5.4.0 之前为 E_STRICT 除外的所有错误和警告信息。PHP 5.4.x 中为 32767, PHP 5.3.x 中为 30719, PHP 5.2.x 中为 6143, 更早之前的 PHP 版本中为 2047。

    try…catch 能做什么

    可以捕获异常和错误,在php中有预定义的异常和错误,系统会自动抛出,这些是可以通过try...catch来捕获的。

    https://www.php.net/manual/en/reserved.exceptions.php

    Exception
    ErrorException
    Error
    ArgumentCountError
    ArithmeticError
    AssertionError
    DivisionByZeroError
    CompileError
    ParseError
    TypeError
    ValueError
    UnhandledMatchError
    FiberError
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    我们最常用的捕获自定义的异常

    try {
        throw new MyException('xxx');
    } catch (MyException $e){
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    假如我们调用了一个未定义的方法,那么内核会抛出一个预定义的Error,比如Uncaught Error: Call to undefined function checkOrderFormats() in /www/chpay/api/order_status.php:29这是一个E_ERROR类型,会导致程序中止。

    此时我们可以这样写

    try {
        checkOrderFormats();
        throw new MyException('xxx');
    } catch (MyException $e){
        
    } catch (Error $e){
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    于是我们会发现,php内置的预定义ExceptionError挺多的,再加上我们自定义的Exception,要想通过try...catch来全部捕获他们实在不现实,也不友好。

    register_shutdown_function

    此函数在php中止时被执行。在这个函数里我们可以获取到没有被try…catch捕获或其他程序处理的错误,并记录到日志文件中。

    register_shutdown_function("shutdownLog");
    
    function shutdownLog()
    {
    	if (!is_null($e = error_get_last())) {
    		addLog($e['message'], "ERROR");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    上面提到的调用了一个未定义的方法会导致程序中止,在此处就可以被捕获到,当然,如果你使用了try...catch捕获了预定义的Error,那么此处就没有了。

    set_error_handler

    设置用户自定义的错误处理函数,自定义的错误类型指的是E_USER_ERROR,E_USER_WARNING,E_USER_NOTICE

    set_error_handler("myErrorHandlerLog", E_ALL ^ E_NOTICE);
    
    function myErrorHandlerLog($errno, $errstr, $errfile, $errline)
    {
    	addLog(sprintf("[%d] %s in %s:%d", $errno, $errstr, $errfile, $errline), "ERROR");
    	return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    此处如果返回false,那么错误信息将会继续向下传导,因此返回true即可。

    上面提到的调用了一个未定义的方法(E_ERROR),在此处没有捕获到,另外它还不能捕获E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、E_COMPILE_WARNING,以及在调用 set_error_handler() 函数所在文件中产生的大多数 E_STRICT

    重要的是要记住 error_types 里指定的错误类型都会绕过 PHP 标准错误处理程序, 除非回调函数返回了 falseerror_reporting() 设置将不会起到作用而你的错误处理函数继续会被调用 —— 不过你仍然可以获取 error_reporting 的当前值,并做适当处理。 需要特别注意的是带 @ error-control operator 前缀的语句发生错误时,这个值会是 0。

    但是我发现它能捕获E_WARNING的错误,比如$a = 10 / 0;

    总结

    最终的错误处理的方式

    error_reporting(E_ALL);
    ini_set('display_errors', FALSE);
    
    // 位置尽量靠前
    register_shutdown_function("shutdownLog");
    set_error_handler("myErrorHandlerLog", E_ALL);
    
    function shutdownLog()
    {
    	if (!is_null($e = error_get_last())) {
    		addLog(sprintf("[%d] %s in %s:%d", $e['type'], $e['message'], $e['file'], $e['line']), "ERROR");
    	}
    }
    
    function myErrorHandlerLog($errno, $errstr, $errfile, $errline)
    {
    	addLog(sprintf("[%d] %s in %s:%d", $errno, $errstr, $errfile, $errline), "ERROR");
    	return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    基本上就能捕获所有的信息了。

  • 相关阅读:
    【CSS】使用 CSS 实现一个宽高自适应的正方形
    【kali-信息收集】(1.5)系统指纹识别:Nmap、p0f
    Vue 3中的provide和inject:跨组件通信的新方式
    Python经典习题(一)
    开源即时通讯(IM)项目OpenIM源码部署流程
    推荐书目:Python从入门到精通(文末送书)
    酷早报:6月23日Web3加密行业每日新闻汇总
    痛定思痛学DP,动态规划的一般性应用流程的总结
    面试突击34:如何使用线程池执行定时任务?
    使用IDEA连接mysql
  • 原文地址:https://blog.csdn.net/raoxiaoya/article/details/126360861