PHP7升级-异常错误处理

想了解更多我的文章,请关注我的博客http://liuxiaochun.cn
PHP最开始只有错误处理,直到PHP5才借鉴了其他语言,引入了异常处理,但是仍然无法处理致命错误,PHP7以后大部分致命错误和可捕获错误(E_ERROR 和 E_RECOVERABLE_ERROR)发生时会抛出异常,可以捕获,而不是停止脚本执行。但是对于某些情况,比如内存分配导致的问题等还会像原来一样直接停止脚本执行。遗憾的是某些情况官方并没有给出明确的规定。总之PHP的异常错误处理,虽然一直不是很清晰,是一个不断发展完善的过程,希望以后的版本会越来越好。

错误

定义

属于php脚本自身的问题,大部分情况是由错误的语法,服务器环境导致,使得编译器无法通过检查,甚至无法运行的情况。

错误常量说明

详见官方定义列表

错误触发

触发分系统触发和用户触发,用户触发可以通过trigger_error产生一个用户级别的 error/warning/notice 信息,分别对应E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE三种错误

错误处理

mixed set_error_handler(callable $error_handler [, int $error_types = E_ALL | E_STRICT ])

注意如下:

  • error_types 里指定的错误类型都会绕过 PHP 标准错误处理程序, 除非回调函数返回了 false。
  • error_types 里指定的错误类型都会触发,跟error_reporting设置没关系,但是可以根据error_reporting做处理。
function _error_handler($errno, $errstr ,$errfile, $errline)
{
    if (error_reporting() & $errno) {
        //todo log;
    }
}

set_error_handler('_error_handler');
  • 注意@前缀语句发生错误时,error_reporting()返回0。@前缀春哥不推荐使用,效率低,而且@用正常错误和异常处理流程完全能搞定。
  • 该函数不会导致脚本退出,会继续执行,所以有需要的话使用die()退出。
  • 该函数目前有些鸡肋,只能处理E_WARNING,E_NOTICE和三种用户错误。

以下级别的错误不能由用户定义的函数来处理: E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,和在 调用 set_error_handler() 函数所在文件中产生的大多数 E_STRICT。

  • 对PHP错误处理建议如下配置:

一定要让 PHP 报告错误;
在开发环境中要显示错误;
在生产环境中不能显示错误;
在开发和生产环境中都要记录错误。

生产环境:

;不显示错误
display_startup_errors = Off
display_errors = Off
;除了NOTICE外,报告所有错误
error_reporting = E_ALL & ~E_NOTICE
; 记录错误
log_errors = On

开发环境:

;显示错误
display_startup_errors = On
display_errors = On
;报告所有错误
error_reporting = -1
; 记录错误
log_errors = On

异常

定义

异常也是一中错误,只不过是一中优秀的处理方式,有如下特点:

  • 异常可以自定义扩展
  • 异常可以抛出和捕获,开发者能够根据具体的错误,进行相应的后续处理。
  • 异常有调用堆栈信息,方便调试。
  • 未被捕获的异常,将以fatal error 的形式中断脚本的执行并输出错误信息

层级

interface Throwable
  |- Error implements Throwable
      |- ArithmeticError extends Error
          |- DivisionByZeroError extends ArithmeticError
      |- AssertionError extends Error
      |- ParseError extends Error
      |- TypeError extends Error
          |- ArgumentCountError extends TypeError
  |- Exception implements Throwable
      |- ClosedGeneratorException extends Exception
      |- DOMException extends Exception
      |- ErrorException extends Exception
      |- IntlException extends Exception
      |- LogicException extends Exception
          |- BadFunctionCallException extends LogicException
              |- BadMethodCallException extends BadFunctionCallException
          |- DomainException extends LogicException
          |- InvalidArgumentException extends LogicException
          |- LengthException extends LogicException
          |- OutOfRangeException extends LogicException
      |- PharException extends Exception
      |- ReflectionException extends Exception
      |- RuntimeException extends Exception
          |- OutOfBoundsException extends RuntimeException
          |- OverflowException extends RuntimeException
          |- PDOException extends RuntimeException
          |- RangeException extends RuntimeException
          |- UnderflowException extends RuntimeException
          |- UnexpectedValueException extends RuntimeException

特殊说明:

  • PHP5中一些无法处理的Fatal Error在PHP7中可以作为Error异常处理。
  • ParseError require或者eval出现语法错误的时候被抛出.
  • TypeError 函数的传参与其对应的声明参数类型不匹配;函数返回值类型与声明的函数返回类型不匹配。将无效数量的参数传递给内置PHP函数。(strict mode only)

异常处理

try/catch

建议在框架的顶层增加try/catch来未能捕获的异常。

set_exception_handler
  • 如果没有用try/catch捕获异常,则会调用该逻辑。
  • 注意与set_error_handler不同的是,该函数调用后会终止脚本。
  • 调用方式如下:
set_exception_handler('handle');//方式一
set_exception_handler(array('App','handle'));//方式二

PHP7升级的变化

set_exception_handler

// 修改前(PHP5代码)
set_exception_handler(function (Exception $e) {
    echo 'Throw Exception: '.$e->getMessage();
});
 
// 修改后(同时兼容PHP5和PHP7代码)
set_exception_handler(function ($e) {
    echo 'Throw Exception: '.$e->getMessage();
});

try/catch

// 修改前(PHP5代码)
try {
    //Code 
} catch (Exception $e) {
    //TODO something
}
// 修改后(同时兼容PHP5和PHP7代码)
try {
    //Code 
} catch (Throwable $t) {
    //TODO something
} catch (Exception $e) {
    //TODO something
}

可能会出现的'BUG'

如下写法可能会导致一些问题, require之前最好判断一下is_file,具体详见https://bugs.php.net/bug.php?id=76636

t.php
<?php
error_reporting(E_ALL^E_NOTICE);
function _exception_handler($e)
{
    var_dump($e);exit(1);
}
set_exception_handler('_exception_handler'); 
spl_autoload_register(function($className) {
    $php = $className . ".php";
    $ret = require_once $php;
    return true;
});
spl_autoload_register(function($className) {
        $php = "namespace\\" . $className . ".php";
        $ret = require_once $php;
        echo $e->getMessage();
        return true;
});
new mytest();
mytest.php
<?php
class mytest {
    fdsaf;//parse error
}

小结

总之PHP异常是错误的一种,在PHP7中错误可以分为可处理错误(set_error_handler),异常(Exception/Error),不可处理错误。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351

推荐阅读更多精彩内容