学习要点
- 修改错误报告级别
- 写错误日志
- 异常处理实现
- 自定义异常
- 捕获多路异常
错误处理
定义
- 错误:开发过程中的失误、用户操作引起的错误。
- 错误产生原因
- 语法错误:开发环境提示,未修正则脚本无法运行。
- 运行时错误:脚本无法正确运行。例如双引号字符串对变量的解析。
- 逻辑错误:常见的逻辑运算错误,循环条件设置错误等等。
错误报告级别
1、WAMP作为开发环境,在php.ini配置文件中,有两个参数设置:
- display_errors = on
注释:PHP解析器将会输出错误报告的功能。如果是产品正式发布部署,需要在PHP服务器上把此项值值为off。
- error_reporting = E_ALL
注释:PHP解析器将输出每个错误。
2、PHP的错误报告级别:
值 |
常量 |
描述 |
1 |
E_ERROR |
Fatal run-time errors. Errors that can not be recovered from. Execution of the script is halted |
2 |
E_WARNING |
Non-fatal run-time errors. Execution of the script is not halted |
4 |
E_PARSE |
Compile-time parse errors. Parse errors should only be generated by the parser |
8 |
E_NOTICE |
Run-time notices. The script found something that might be an error, but could also happen when running a script normally |
16 |
E_CORE_ERROR |
Fatal errors at PHP startup. This is like an E_ERROR in the PHP core |
32 |
E_CORE_WARNING |
Non-fatal errors at PHP startup. This is like an E_WARNING in the PHP core |
64 |
E_COMPILE_ERROR |
Fatal compile-time errors. This is like an E_ERROR generated by the Zend Scripting Engine |
128 |
E_COMPILE_WARNING |
Non-fatal compile-time errors. This is like an E_WARNING generated by the Zend Scripting Engine |
256 |
E_USER_ERROR |
Fatal user-generated error. This is like an E_ERROR set by the programmer using the PHP function trigger_error() |
512 |
E_USER_WARNING |
Non-fatal user-generated warning. This is like an E_WARNING set by the programmer using the PHP function trigger_error() |
1024 |
E_USER_NOTICE |
User-generated notice. This is like an E_NOTICE set by the programmer using the PHP function trigger_error() |
2048 |
E_STRICT |
Run-time notices. PHP suggest changes to your code to help interoperability and compatibility of the code |
4096 |
E_RECOVERABLE_ERROR |
Catchable fatal error. This is like an E_ERROR but can be caught by a user defined handle (see also set_error_handler()) |
8191 |
E_ALL |
All errors and warnings, except level E_STRICT (E_STRICT will be part of E_ALL as of PHP 6.0) |
3、开启错误报告
处理在php.ini文件中配置,如果对服务器权限不够,可以采用ini_set()函数设置:
例如:
ini_set(‘display_errors’,1);
调整错误报告级别
1、在php.ini中修改配置指令error_reporting的值
默认值:
error_reporting = E_ALL
修改示例1(结合位运算符&,|,~):除运行时注意消息外的全部错误报告
error_reporting = E_ALL&~E-NOTICE;
修改示例2:只考虑运行时错误、解析错误、核心错误
error_reporting = E_ERROR | E_PARSE | E_CORE_ERROR
2、在脚本中使用error_reporting()函数
权限不够,或者需要个性化页面错误报告,采用该函数。
error_reporting(0); //完全关闭错误报告 error_reporting(E_ALL); //报告任何错误 error_reporting(E_ALL&~E_NOTICE); //报告除注意外的任何错误
示例:
/* 开启php.ini中的display_errors指令*/ ini_set ( 'display_errors', 1); /* 通过error_reporting()函数设置在本脚本中,输出所有级别的错误报告 */ error_reporting ( E_ALL ); //error_reporting ( E_ALL &~(E_WARNING|E_NOTICE)); /* “注意(notice)”的报告,不会阻止脚本的执行,并且可能不一定是一个问题 */ getType ( $var ); // 调用函数时提供的参数变量没有在之前声明 /* “警告(warning)”的报告,指示一个问题,但是不会阻止脚本的执行 */ getType (); // 调用函数时没有提供必要的参数 /* “错误(error)”的报告,它会终止程序,脚本不会再向下执行 */ get_Type (); // 调用一个没有被定义的函数
使用trigger_error()函数代替die()函数
die()等同于exit(),会退出程序。而trigger_error()可以生成一个用户警告来代替退出程序。
示例代码:
//die("程序运行结束!"); trigger_error("there is a bugbugbug!",E_USER_WARNING); echo "这里是php文件尾巴";
自定义错误处理
1、需要自定义错误信息的情形
- 记录错误信息
- 屏蔽错误信息
- 错误统一输出页面处理或者同一页面位置输出错误信息
- 调试
2、如何自定义错误处理
用户自定义错误处理函数:set_error_handler()
语法格式:
mixed set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRICT ] )
参数说明:
error_handler:
handler ( int $errno , string $errstr [, string $errfile [, int $errline [, array $errcontext ]]] ) //四个参数含义:错误级别、错误信息、错误所在文件,错误所在文件第几行
error_types:
错误报告级别。默认E_ALL。
示例代码:
// 屏蔽所有错误报告 error_reporting ( 0 ); function error_handler($error_level, $error_message, $file, $line) { $EXIT = false; $error_type=''; switch ($error_level) { //提醒 case E_NOTICE : case E_USER_NOTICE : $error_type = 'Notice'; break; //警告 case E_WARNING : case E_USER_WARNING : $error_type = 'Warning'; break; //错误 case E_ERROR : case E_USER_ERROR : $error_type = 'Fatal Error'; break; //未知错误 default: $error_type = 'Unknown'; $EXIT=true; break; } //打印错误信息,可以自定义错误格式 printf("%s,%s,%s,%d",$error_type,$error_message,$file,$line); if(true==$EXIT){ echo '<script>location="error.php";</script>'; } } set_error_handler('error_handler'); //echo $novar; echo 3/0;
注意:
1、set_error_handler()不处理以下错误报告:E_ERR0R、E_PARSE、E_CORE_ERROR、E_CORE_WARNING、E_COMPILE_ERROR、E_COMPILE_WARNING。不处理不等于不显示错误信息,它不会按照用户设定格式显示。
2、除了第1条中列出的错误,在使用了set_error_handler()函数后,所有的错误都交给用户处理。
上机练习1:自定义错误处理
1、 set_error_handler()函数的用法
2、 自定义回调函数
3、 错误报告格式:
写错误日志
PHP项目部署运行后,一般display_errors = off。程序日常运行的错误信息是需要记录下来,作为运维参考,如何处理?有两种记录日志的方式:
1、使用指定的文件记录错误报告日志
php.ini配置
error_reporting = E_ALL
display_errors = off
log_errors=on
log_errors_max_len = 1024
error_log = "d:/wamp/logs/php_error.log"
error_log()函数
//写入操作系统日志 (需要php.ini中设置error_log=syslog) error_log("error message",0); //发送到电子邮件(需要邮件服务器) error_log("error message",1,"2083967667@qq.com"); //发送到某个ip的某个端口 error_log("error message",2,"localhost:5000"); //写入到某个路径文件中 error_log("error message",3,"er.log");
2、错误信息记录到操作系统日志中
php.ini配置
error_reporting = E_ALL
display_errors = off
log_errors=on
log_errors_max_len = 1024
error_log = syslog
使用syslog向系统发送订制消息
//php5.3开始,已经废除相关函数 define_syslog_variables(); ……
异常处理
定义
Exception:在程序执行过程中出现的一个例外或是一个事件,它中断了正常指令的运行,跳转到其他程序模块继续执行。
简单异常处理
1、语法结构
try{ //需要捕获异常的代码块 }catch (Exception $ex1){ //处理异常 } finally { //始终被执行的代码 }
2、示例代码
try { $number = 100; $div = 0; if ($div == 0) { throw new Exception ( "除数不能为0" ); } $result=$number/$div; echo '计算结果'.$result; } catch ( Exception $e ) { echo '程序异常:'.$e->getMessage(); }finally { echo '<br>finally代码始终执行'; } echo '<br>程序继续执行';
自定义异常处理类
1、内置Exception类结构
class Exception { protected $message = 'Unknown exception'; // 异常信息 protected $code = 0; // 用户自定义异常代码 protected $file; // 发生异常的文件名 protected $line; // 发生异常的代码行号 function __construct($message = null, $code = 0); final function getMessage(); // 返回异常信息 final function getCode(); // 返回异常代码 final function getFile(); // 返回发生异常的文件名 final function getLine(); // 返回发生异常的代码行号 final function getTrace(); // backtrace() 数组 final function getTraceAsString(); // 已格成化成字符串的 getTrace() 信息 /* 可重载的方法 */ function __toString(); // 可输出的字符串 }
2、自定义异常处理类
/* 自定义异常处理类 */ class MyException extends Exception { // 重写构造函数 public function __construct($message, $code = 0) { parent::__construct ( $message, $code ); } /*重写父类__toString魔术方法*/ public function __toString() { return __CLASS__ . ":[" . $this->code . "]:" . $this->message . "<br>"; } /*自定义异常方法*/ public function customFunction() { echo "按自定义的方法处理出现的这个类型的异常<br>"; } } try { $error = '允许抛出这个错误'; throw new MyException ( $error ); echo '出现异常,不被执行的代码.....'; } catch ( MyException $e ) { echo '捕获异常: ' . $e; $e->customFunction (); } echo '程序继续执行......';
上机练习2:自定义异常处理
多路异常捕获
class MyException extends Exception { public function __construct($message, $code = 0) { parent::__construct ( $message, $code ); } public function __toString() { return __CLASS__ . ":[" . $this->code . "]:" . $this->message . "<br>"; } public function customFunction() { echo "按自定义的方法处理出现的这个类型的异常"; } } class TestException { public $var; function __construct($value = 0) { switch ($value) { case 1 : throw new MyException ( "传入的值“1” 是一个无效的参数", 5 ); break; case 2 : throw new Exception ( "传入的值“2”不允许作为一个参数", 6 ); break; default : $this->var = $value; break; } } } // 示例1,在没有异常时,程序正常执行,try中的代码全部执行并不会执行任何catch区块 $testObj=null; try { $testObj = new TestException (); // 使用默认参数创建异常的测试类对象 echo "***********<br>"; // 没有抛出异常这条语句就会正常执行 } catch ( MyException $e ) { // 捕获用户自定义的异常区块 echo "捕获自定义的异常:$e <br>"; // 按自定义的方式输出异常消息 $e->customFunction (); // 可以调用自定义的异常处理方法 } catch ( Exception $e ) { // 捕获PHP内置的异常处理类的对象 echo "捕获默认的异常:" . $e->getMessage () . "<br>"; // 输出异常消息 } var_dump ( $testObj ); // 判断对象是否创建成功,如果没有任何异常,则创建成功 // 示例2,抛出自定义的异常,并通过自定义的异常处理类捕获这个异常并处理 $testObj1=null; try { $testObj1 = new TestException ( 1 ); // 传入参数1时,创建测试类对象抛出自定义异常 echo "***********<br>"; // 这个语句不会被执行 } catch ( MyException $e ) { // 这个catch区块中的代码将被执行 echo "捕获自定义的异常:$e <br>"; $e->customFunction (); } catch ( Exception $e ) { // 这个catch区块不会执行 echo "捕获默认的异常:" . $e->getMessage () . "<br>"; } var_dump ( $testObj1 ); // 有异常产生,这个对象没有创建成功 //示例2,抛出内置的异常,并通过自定义的异常处理类捕获这个异常并处理 $testObj2=null; try { $testObj2 = new TestException ( 2 ); // 传入参数2时,创建测试类对象抛出内置异常 echo "***********<br>"; // 这个语句不会被执行 } catch ( MyException $e ) { // 这个catch区块不会执行 echo "捕获自定义的异常:$e <br>"; $e->customFunction (); } catch ( Exception $e ) { // 这个catch区块中的代码将被执行 echo "捕获默认的异常:" . $e->getMessage () . "<br>"; } var_dump ( $testObj2 ); // 有异常产生,这个对象没有创建成功