实验
承接上一篇:https://mengkang.net/978.html
Symfony 命令行是如何把错误转成异常的呢?
原来是使用了ErrorException
有了这个类就太好了,命令行可能感触不是特别明显,对于 web 来说简直就是福音了。
下面做一个小实验,当什么都没有设置的时候,以下代码和其错误信息如下:
function testError(){
return explode("xxx");
}
testError();
[21-Mar-2018 15:42:25 PRC] PHP Warning: explode() expects at least 2 parameters, 1 given in /xxx/test.php on line 4
看不到具体的参数,也看不到调用栈。这里没有演示,比如很多函数的相互嵌套调用。仅仅这一行,很难知道这个请求的具体流程。(这一行演示不明显,可以自己加几个文件的包含)。
将代码改成
function testError(){
return explode("xxx");
}
try{
testError();
}catch(Exception $e){
var_export($e->getTrace());
}
echo 1;
页面能正常输出1
,但是无法打印出异常的调用栈,php 错误日志里面和没有使用try-catch 一样,没有调用栈。
改进
然后我们如果使用set_error_handler
+ ErrorException
之后,就非常清晰了,很便于错误的追踪。
function my_error_handler($severity, $message, $file, $line) {
throw new ErrorException($message, 0, $severity, $file, $line);
}
set_error_handler("my_error_handler");
function testError(){
return explode("xxx");
}
try{
testError();
}catch(Exception $e){
var_export($e->getTrace());
}
最后打印出来的信息就是
array (
0 =>
array (
'function' => 'exception_error_handler',
'args' =>
array (
0 => 2,
1 => 'explode() expects at least 2 parameters, 1 given',
2 => '/Users/zhoumengkang/Downloads/xxx.php',
3 => 19,
4 =>
array (
),
),
),
1 =>
array (
'file' => '/Users/zhoumengkang/Downloads/xxx.php',
'line' => 19,
'function' => 'explode',
'args' =>
array (
0 => 'xxx',
),
),
2 =>
array (
'file' => '/Users/zhoumengkang/Downloads/xxx.php',
'line' => 12,
'function' => 'testError',
'args' =>
array (
),
),
)
这样就能看见着整个调用栈和每个函数的传递的参数。不仅仅是这些信息,因为通过set_error_handler
接管了错误处理,所以在出现该错误的其他信息都可以记录了,方便错误的重现和追踪。
Uncaught TypeError
set_error_handler(function ($severity, $message, $file, $line) {
throw new ErrorException($message, 0, $severity, $file, $line);
});
function testError1($context){
return explode($context);
}
function testError2(array $context){
return false;
}
try{
// testError1(111);
testError2(111);
}catch(Exception $e){
var_export($e->getTrace());
}
Fatal error: Uncaught TypeError: Argument 1 passed to testError2() must be of the type array, integer given, called in
改进,但有不足
set_error_handler(function ($severity, $message, $file, $line) {
throw new ErrorException($message, 0, $severity, $file, $line);
});
register_shutdown_function(function(){
$e = error_get_last();
if ($e){
var_export($e);
}
});
function testError1($a){
return $a*10;
}
function testError2(array $context){
return false;
}
try{
$b = testError1(6666);
testError2($b);
}catch(Exception $e){
var_export($e->getTrace());
}
array (
'type' => 1,
'message' => 'Uncaught TypeError: Argument 1 passed to testError2() must be of the type array, integer given, called in xxx.php on line 32 and defined in xxx.php:26
Stack trace:
#0 xxx.php(32): testError2(66660)
#1 {main}
thrown',
'file' => 'xxx.php',
'line' => 26,
)
依然看不到完整的调用栈。