之所以想着做错误和异常的自动处理是因为:

    用的公司自己的框架写API,没有异常和错误相关功能,

    而每次操作都进行try...catch,有点繁琐不说,感觉还很鸡肋,即使我catch到了,还是得写代码进行处理,哪怕封装了一个方法进行处理也还是繁琐,

    这种情况应该是程序自动进行处理,不该是这样弱智的人工try...catch,然后处理

    以及其他同事写代码时并不能严格的进行try...catch

    于是乎,想自己设计一个自动捕获并处理错误和异常的功能。

  发现了一篇深度好文:https://www.cnblogs.com/zyf-zhaoyafei/p/6928149.html

     理解了PHP中自带的  register_shutdown_function,set_error_handler,set_exception_handler这三个函数

  通过这三个函数我们可以实现PHP假 自动捕获异常和错误。PHP5也不支持ERROR的捕获,只能try...catch (Exception)

  三个函数必须理解,如果你想实现该功能,希望你可以先做个小demo体验下三个函数的神奇之处

  这三个函数需要你写在框架的生命周期比较靠前的地方,如果不知道写哪里,请写在入口文件中,或者在入口文件require一下(下面的源码可以直接require使用)

  因为如果写到其他文件中,而碰巧该文件有错误或者异常,那么这三个函数就不发生作用了,而入口文件我们都可以确保正确

  正文:

      首先介绍set_error_handler这个函数,这个函数用于捕获低级别的错误,该函数只能捕获系统产生的一些Warning、Notice级别的错误,并调用一个用户自定义的错误处理函数。

    比如在入口文件写入  set_error_handler('low_level_error'),并且我们建立了low_level_error 自定义方法来进行日志的记录 。

    当发生Warning、Notice级别的错误时,系统会自动调用low_level_error方法,四个参数"type"、 "message"、"file" 和 "line"也是系统传过来的,可以直接使用。

    注意:使用此函数后  error_reporting ( E_ALL )  无法提示warning和notice级别的警告, 如果本地开发,最好关闭此函数,在生产环境才使用;  使用 其它两个函数 时错误提示信息不受影响

    可以使用下面源码中的单个方法进行测试, 只需echo $str; exit; 就好

      第二个函数 register_shutdown_function, 这个函数与第一个函数搭配使用,可以捕捉到Fatal Error、Parse Error等高级别会让程序中止的错误,

    这个方法是PHP脚本执行结束前最后一个调用的函数,比如脚本错误、die()、exit、异常、正常结束都会调用。这个方法没有接受参数,所以需要借助error_get_last() ,error_get_last函数可以获取到

    系统最近发生的一个错误,同样包含  "type"、 "message"、"file" 和 "line"四个字段,需要注意的是 本函数捕捉到的 (2,8,32,128,512,1024,2048,8192)等错误都是警告级别的,自己酌情处理。

      第三个函数set_exception_handler, 这个函数可以捕获 没有用try/catch块来捕获的异常,并且在回调函数调用后异常会中止(这个我没有试,因为我捕捉异常后直接返回给前端错误code码了)。

  思路:通过set_error_handler 和 register_shutdown_function 两个函数可以捕捉到所有的错误,通过set_exception_handler 捕捉所有未处理的异常,这样程序中所有的错误和异常就被我们捕捉到了,

    接下来,我们可以通过自定义函数对它们进行操作,由于我的业务是直接向前端输出,因此只是记录相关日志后直接echo并退出,大家可以在自定义函数内自己决定做什么处理。

    还可以在两个自定义的错误处理函数中再抛出异常,由自定义的异常处理类统一处理,这也是一个不错的思路,大家可以尝试下。

  最后:

    下面是相关的代码,供大家参考和测试。

<?php
/**引入本文件后,PHP会自动处理错误和异常, php版本5.6, php7+版本需要小调整,运行时根据提示调整即可
* 本方法直接捕捉错误并记录日志,如有兴趣,可以捕捉到错误后再次抛出异常,将错误转为异常后,由set_exception_handler统一进行处理
* User: LiZheng 271648298@qq.com
* Date: 2019/3/21
*/
register_shutdown_function('high_level_error'); //使用了register_shutdown_function 后,当程序遇见一些致命错误时会自动调用函数 high_level_error
set_error_handler('low_level_error'); //使用了set_error_handler 后,当程序遇见Notice 和Warning错误时会自动调用函数 low_level_error
set_exception_handler('exception_log'); //使用了set_exception_handler后,当遇到所有的未捕获的异常时会自动调用函数 exception_log
/**
* 该方法只能捕获系统产生的一些Warning、Notice级别的错误
* @param $type
* @param $message
* @param $file
* @param $line
* User: LiZheng 271648298@qq.com
* Date: 2019/3/21
*/
function low_level_error($type, $message, $file, $line)
{
$time = date('Y-m-d H:i:s');
//拼接要记录成日志的信息
$str = "\n ".$time.' set_error_handler: ' . exception_self::get_type($type) . ':' . $message . ' in ' . $file . ' on ' . $line . ' line .';
$str = addslashes($str);
//记录日志 error_log是PHP自带函数,记录到指定位置,详情见官网
error_log($str,3,ROOT_DIR."/runtime/logs/php_error.log"); //ROOT_DIR为项目根目录
//对于notice和warning 级别的错误,只进行记录而不会终止程序(但在本地开发时希望提示,可以通过if语句判断)
//echo json_encode(array('code'=>“ERR_ERROR”, 'msg'=>$time, 'data'=>array()), true);exit;
} /**
* 捕捉一些致命错误
* User: LiZheng 271648298@qq.com
* Date: 2019/3/21
*/
function high_level_error()
{
//error_get_last() 获取最近一条发生的错误,包含"type"、 "message"、"file" 和 "line"
if ($error = error_get_last()) {
$time = date('Y-m-d H:i:s');
//拼接要记录成日志的信息
$str = "\n ".$time.' register_shutdown_function: Type:' . exception_self::get_type($error['type']) . ' Msg: ' . $error['message'] . ' in ' . $error['file'] . ' on line ' . $error['line'];
$str = addslashes($str);
//记录日志 error_log是PHP自带函数,记录到指定位置,还可以发送邮件以及其他操作
error_log($str,3,ROOT_DIR."/runtime/logs/php_error.log"); //ROOT_DIR为项目根目录
//直接输出接口的返回信息, 给前端一个错误码code, msg返回时间用于方便查找日志
//echo json_encode(array('code'=>“ERR_ERROR”, 'msg'=>$time, 'data'=>array()), true);exit;
if(in_array($error['type'], array(2,8,32,128,512,1024,2048,8192)))//本条件中的错误均为非致命错误, 8192 错误是弃用提示
{
// if(APP_ENV == 'LOCAL') //这里可以对本地开发环境时进行不同的处理
// {
// header('Content-Type: text/html; charset=utf-8');
// echo $str."\n";
// }
}else
{
// if(APP_ENV == 'LOCAL')
// {
// header('Content-Type: text/html; charset=utf-8');
// echo $str."\n";
// }
//直接输出接口的返回信息, 给前端一个错误码code, msg返回时间用于方便查找日志
echo json_encode(array('code'=>ERR_ERROR, 'msg'=>$time, 'data'=>array()), true);exit;
}
}
} /**
* 捕捉异常
* @param $exception
* User: LiZheng 271648298@qq.com
* Date: 2019/3/21
*/
function exception_log($exception)
{
$time = date('Y-m-d H:i:s');
//拼接要记录成日志的信息
$str = "\n ".$time." set_exception_handler: Exception: ". $exception->getMessage()." in ".$exception->getFile()." on line ". $exception->getLine();
$str = addslashes($str);
//记录日志
error_log($str,3,ROOT_DIR."/runtime/logs/php_error.log");
//输出信息
echo json_encode(array('code'=>“ERR_EXCEPTION”, 'msg'=>$time, 'data'=>array()), true);exit;
} /**
* Class error_handler
* Create on 2019/3/21 14:15
* User: LiZheng 271648298@qq.com
* Date: 2019/3/21
*/
class exception_self extends Exception
{
/**
* 构造函数
* @param string $message
* @param string $code
*/
public function __construct($message=null, $code=null)
{
parent::__construct($message, $code);
// self::log($this->__toString());
}
//PHP的错误级别
public static $type = array(
'1' => 'E_ERROR ',
'2' => 'E_WARNING ',
'4' => 'E_PARSE ',
'8' => 'E_NOTICE ',
'16' => 'E_CORE_ERROR ',
'32' => 'E_CORE_WARNING ',
'64' => 'E_COMPILE_ERROR ',
'128' => 'E_COMPILE_WARNING ',
'256' => 'E_USER_ERROR ',
'512' => 'E_USER_WARNING ',
'1024' => 'E_USER_NOTICE ',
'2048' => 'E_STRICT ',
'4096' => 'E_RECOVERABLE_ERROR ',
'8191' => 'E_ALL ',
); /**
* 通过数字 置换 对应的英文
* @param $key
* @return mixed
* User: LiZheng 271648298@qq.com
* Date: 2019/3/21
*/
public static function get_type($key)
{
if(isset(self::$type[$key]))
{
return self::$type[$key];
}else
{
return $key;
}
}
}

关于PHP自动捕捉处理错误和异常的尝试的更多相关文章

  1. C#不用union,而是有更好的方式实现 .net自定义错误页面实现 .net自定义错误页面实现升级篇 .net捕捉全局未处理异常的3种方式 一款很不错的FLASH时种插件 关于c#中委托使用小结 WEB网站常见受攻击方式及解决办法 判断URL是否存在 提升高并发量服务器性能解决思路

    C#不用union,而是有更好的方式实现   用过C/C++的人都知道有个union,特别好用,似乎char数组到short,int,float等的转换无所不能,也确实是能,并且用起来十分方便.那C# ...

  2. php错误及异常捕捉

    原文:php错误及异常捕捉 在实际开发中,错误及异常捕捉仅仅靠try{}catch()是远远不够的. 所以引用以下几中函数. a)   set_error_handler 一般用于捕捉  E_NOTI ...

  3. PHP错误与异常

    请一定要注意,没有特殊说明:本例 PHP Version < 7 说起PHP异常处理,大家首先会想到try-catch,那好,我们先看一段程序吧:有一个test.php文件,有一段简单的PHP程 ...

  4. Java错误和异常

    Java 异常结构图 在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出).Throwable 指定代码中可用异常传播机制通过 Java 应用程序传输的任何问题的共性.  Th ...

  5. php中的错误和异常

    总结: php错误不会抛出异常,因此不能被catch,但会根据配置写入日志文件或者输出到浏览器,所以可以通过日志文件查看错误 php异常都必须自己抛出,并通过catch捕捉.SQL语句执行的错误好像可 ...

  6. Python学习笔记五:错误与异常

    一:常见异常与错误 BaseException 所有异常的基类SystemExit 解释器请求退出KeyboardInterrupt 用户中断执行(通常是输入^C)Exception 常规错误的基类S ...

  7. React中如何优雅的捕捉事件错误

    React中如何优雅的捕捉事件错误 前话 人无完人,所以代码总会出错,出错并不可怕,关键是怎么处理. 我就想问问大家react的错误怎么捕捉呢? 这个时候: 小白:怎么处理? 小白+: ErrorBo ...

  8. python学习笔记014——错误和异常

    Python有两种错误很容易辨认:语法错误和异常. 1 什么是语法错误 Python 的语法错误或者称之为解析错,是初学者经常碰到的,如下实例 if i>4 print("if语句输出 ...

  9. 2015/9/10 Python基础(11):错误和异常

    程序在执行的过程中会产生异常,出现错误在以前的一个时期是致命的,后来随着程序的发展,使得一些错误的处理方式是柔和的,发生错误会产生一些错误的诊断信息和一些模糊的提示.帮助我们来处理异常.今天将学习Py ...

随机推荐

  1. struct的匿名用法详解

    Go只提供类型而不用写字段名的方式,也就是匿名字段,也称为嵌入字段. 当匿名字段是一个struct的时候,那么这个struct所拥有的全部字段都被隐式地引入了当前定义的这个struct. 举个例子,看 ...

  2. TJU ACM-ICPC Online Judge—1191 The Worm Turns

    B - The Worm Turns Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Su ...

  3. GNOME图形界面的基本操作

    成功登录进入CentOS系统之后,我们首先看到的桌面就是GNOME图形界面,下面来看一下相关的基本操作. 个性化设置 1,设置屏幕分辨率 进入菜单 2,更换桌面背景 进入下面菜单. 选择一张背景图片, ...

  4. 灵活使用 console 让 js 调试更简单

    摘要: 玩转console. 原文:灵活使用 console 让 js 调试更简单 作者:前端小智 Fundebug经授权转载,版权归原作者所有. Web 开发最常用的就是 console.log , ...

  5. 20190328-CSS样式一:字体样式font-、文本样式text-、背景图样式background-

    目录 CSS参考手册:http://css.doyoe.com/ 1.字体简写:font:font-style || font-variant || font-weight || font-size ...

  6. 12月16日广州.NET俱乐部下午4点爬白云山活动

    正如我们在<广州.NET微软技术俱乐部与其他技术群的区别>和<广州.NET微软技术俱乐部每周三五晚周日下午爬白云山活动>里面提到的, 我们会在每周三五晚和周日下午爬白云山.   ...

  7. JavaScript函数继承

    在ES6中有了继承,使用extends关键字就能实现.但这里讲的讲的不是这种,而是ES6之前的几种实现继承的方式. (一)原型继承 ECMAScript中将原型链作为实现继承的主要方法.其基本思想是利 ...

  8. OpenCL中的half与float的转换

    在kernel中使用half类型可以在牺牲一定精度的代价下来提升运算速度. 在kernel中, 可以比较方便的对half数据进行计算, 但在host上的, 对half的使用就没那么方便了. 查看cl_ ...

  9. MAC MAMP 中安装配置使用 ThinkPHP

    MAMP PRO 是Mac OS X 平台上经典的本地环境应用 MAMP 的专业版.专门为专业的Web开发人员和程序员轻松地安装和管理自己的开发环境. MAMP这几个首字母代表Mac OS X系统上的 ...

  10. 18-10-31 Scrum Meeting 3

    1.会议照片 2.每人的工作 昨天完成的工作   1 制定配置 修改配置 查询配置这三个接口   2 3 获取单词对应的中文释义   4 完成测验的部分接口   5 后端对接计划的接口   6 剩余的 ...