PHP - 错误处理 | 异常处理

错误处理简介

PHP独有的处理
默认情况下,当错误发生的时候在浏览器上显示错误报告。
可以使用操作符(@)来屏蔽语句生成的错误报告,注意@符号只对函数有用,对echo语句不起作用

错误级别

按照错误的严重程度将错误划分为3种
Notice:提示性错误
Warning:警告性错误
Fatal error:致命性错误

notice和warning级别错误后继续执行,error级别错误后终止执行

处理方式

显示错误报告【默认】
记录错误日志
错误发生后交个自定义脚本去完成【比如,错误发生后发一个电子邮件】

错误触发

PHP程序触发:PHP在运行的过程中,发现并触发错误。比如include、require等等。
由用户触发,通过trigger_error()来触发错误。
eg:定义年龄不能超过30,超过30即报错

1
2
3
$age = 30;
if($age>30)
trigger_error("age cannot over 30",E_USER_ERROR);

用户错误的级别,他们是常量,默认触发notice错误。

1
2
3
;E_USER_ERROR	- user-generated error message
;E_USER_WARNING - user-generated warning message
;E_USER_NOTICE - user-generated notice message

实现错误处理

更改php配置有3种方法

在php.ini中更改

所有的虚拟目录中有效

.htaccess分布式部署文件

.htaccess通过php_flag和php_value 在某个虚拟目录,或某个目录有效.

ini_set():某一个页面有效

ini_set('display_errors':'on') 开启错误显示
ini_set('display_errors':'off') 关闭错误显示

在浏览器上显示错误报告

display_errors = On

在日志中显示错误报告

log_errors = On
错误日志保存的地址
error_log = php_errors.log

用户自定义错误处理

默认情况下,一旦定义了错误处理函数,则错误报告和错误日志不再执行

1
2
3
4
5
6
7
<?php
function error(){
echo '这是自定义错误';
}
//注册错误处理函数
set_error_handler('error');
?>

在自定义错误处理函数中添加return false,则自定义错误处理后再交个PHP处理。

应用:不同的级别使用不同错误处理

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
<?php
/**
*@param $level 错误级别
*@param $msg 错误信息
*@param $file 错误文件
*@param $line 错误行号
*/
function error($level,$msg,$file,$line) {
switch($level) {
case E_NOTICE:
case E_USER_NOTICE:
echo '将错误信息屏蔽掉<br>';
break;
case E_WARNING :
case E_USER_WARNING:
echo '将错误信息记录到日志中<br>';
break;
case E_ERROR:
case E_USER_ERROR:
echo '给管理员发邮件<br>';
break;
}
echo "错误信息:{$msg}<br>";
echo "错误文件:{$file}<br>";
echo "错误行号:{$line}";
}
set_error_handler('error'); //注册错误处理函数
header('content-type:text/html;charset=utf-8');
echo $aa,'<hr>';
include './aa.php';
?>

指定显示错误级别

;Error Level Constants:
error_reporting = E_ALL | E_STRICT
思考:为什么在php5.3中显示所有错误是E_ALL | E_STRICT?
答:在php5.3中,E_ALL不是表示所有错误,E_ALL | E_STRICT也表示所有错误。
在php5.4以上版本,E_ALL的错误都会报的。

E_ALL: 111011111111111
E_STRICT:000100000000000

例题:
只有PHP的notice才报错
ini_set('error_reporting',E_NOTICE);
只报PHP的notice和用户的notice
ini_set('error_reporting',E_NOTICE | E_USER_NOTICE);
系统的notice不报,其他全报
ini_set('error_reporting',(E_ALL | E_STRICT) & ~E_NOTICE);

~是按位取非,0变成1,1变成0。

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
<?php 
/**
* 自定义错误处理函数
* @param int $level 错误级别
* @param string $msg 错误信息
* @param string $file 错误文件名
* @param int $line 错误行号
* @return Bool 错误处理情况
*/
function error($level,$msg,$file,$line){
switch ($level) {
case E_NOTICE:
case E_USER_NOTICE:
echo '将错误屏蔽';
break;
case E_WARNING:
case E_USER_WARNING:
echo '将错误记录在日志中<br>';
break;
// case E_ERROR: //一般不设置,若报了该错误,程序将终止运行
case E_USER_ERROR:
echo '将错误发送给管理员<br>';
break;
}
echo '错误信息:'.$msg,"<br>";
echo '错误文件:'.$file."<br>";
echo '错误行号:'.$line,'<br>';
// return false 自定义错误处理完毕后,交给计算机继续处理
return false;
}
// 注册错误函数
set_error_handler('error');
?>

项目中的错误处理

项目开发的时候错误显示在浏览器上,不用记录在日志中
项目运行的时候错误记录在日志中,不显示在浏览器上

  • php.ini log_errors = on 开启错误日志
  • php.ini error_log = $log_path.$error_log;

将项目的运行模式分为“开发模式(调试模式)”和“运行模式”

  • 在配置文件中,添加一个配置用来保存开发的模式
  • 在Application文件夹下新建Log文件夹,用来保存日志
  • 在Framework类中添加定义Log文件夹的路径常量
  • 在Framework类中定义错误处理的方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <?php 
    private static function initError(){
    ini_set('error_reporting', E_ALL | E_STRICT); //报所有错误
    if($GLOBALS['config']['app']['app_dubeg']){//开发模式
    ini_set('display_errors','on'); //浏览器显示错误
    ini_set('log_errors','off'); //不记录日志
    }else{
    ini_set('display_errors','off'); //浏览器不显示错误
    ini_set('log_errors','on'); //记录日志
    $error_log = date('Y-m-d').'.log';
    ini_set('error_log',LOG_PATH.$error_log);
    }
    }
    ?>

异常处理

异常处理使用关键字:try、catch、throw

  1. try:用来监测代码
  2. thr ow:用来抛出异常
  3. catch:用来捕获异常
  4. Exception:PHP内置的异常类,是所有异常类的父类
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<?php
if(isset($_POST['button'])){
try{
$age = $_POST['age'];
if ($age<20 || $age>30) {
throw new Exception('年龄必须在20到30之间');//抛出异常类
echo '错误抛出后这里不会再执行了';
}else{
echo '青春年少,用行动做一辈子不能被注定的事!';
}
}catch(Exception $e){ //数据类型约束,只能是Exception
//catch 用来捕获错误
echo '错误信息:'.$e->getMessage().'<br>';
echo '异常码:'.$e->getCode().'<br>';
echo '当前文件:'.$e->getFile().'<br>';
echo '异常行号:'.$e->getLine().'<br>';
}
}
?>
<form action="" method="post">
请输入年龄:<input type="text" name="age"><br>
<input type="submit" name="button" value="提交">
</form>
</body>
</html>