PHP 错误调查

一.定义:PHP错误是由PHP没法读懂执行的代码引发的错误。php

二:错误日志 error log
1.在php.ini 里设置 log_errors = on, log文件位置 error_log=/tmp/php_errors.log
2.代码里设置ini_set('log_errors' , 1) ,log文件位置 ini_set('error_log','/tmp/php_errors.log')
若是 error_log值为空,PHP会把错误传递到web服务器,PHP错误会被记录到web服务器的错误日志里。
在Apache 服务器,错误日志文件路径在httpd.conf : ErrorLog "/var/log/apache2/error_log"
若是你没法找到Apache 错误日志的位置,你能够在你的错误代码以前添加 
ini_set('log_errors' , 1)   
ini_set('error_log','/tmp/php_errors.log')
确保web服务器有写入 error_log的权限,若是没有的话,PHP会继续使用web服务器的错误日志文件。程序员

三:错误打印 error printing
除了写入错误日志,PHP还支持把错误输出到页面,或者是在命令行界面标准输出。打开错误打印的设置:
1.在php.ini里设置display_errors =1
2.ini_set('display_errors')web

若是你正确配置了全部的这些参数,可是错误信息没有输出,并且错误日志里也没有任何信息,或者界面出现白屏,怎么办?apache

四:错误报告 error reporting
除了能够配置错误日志的位置,PHP容许你来配置系统中哪些错误被当作错误来处理。这一操做可经过:error_reporting或者 error_reporting ini 实现
举例:小程序

error_reporting(E_ALL | E_STRICT);  //trust us on this line for now
echo $foo;
echo "Done","\n";

若是你运行以上代码会出现: Notice : Undefined variable :foo in ......
若是是安全

error_reporting(E_PARSE);  //trust us on this line for now
echo $foo;
echo "Done","\n";

 PHP不会输出或者记录任何错误。
 服务器

五:错误级别 Error level
PHP目前有16个错误级别网络

E_ERROR
E_WARNING
E_PARSE
E_NOTICE
E_CORE_ERROR
E_CORE_WARNING
E_COMPILE_ERROR
E_COMPILE_WARNING
E_USER_ERROR
E_USER_WARNING
E_USER_NOTICE
E_STRICT
E_RECOVERABLE_ERROR
E_DEPRECATED
E_USER_DEPRECATED
E_ALL

 

六:定制化错误处理
set_error_handle 容许用户定义本身的错误处理方法。
 app

#File: example.php
function ourMagicErrorHandler($error_level, $error_string, $error_file, $error_line, $error_context)
{
    echo "An error happened but we're not going to say which one","\n";
    return true;
}
set_error_handler('ourMagicErrorHandler');

error_reporting(E_ALL | E_STRICT);  //trust us on this line for now
echo $foo;
echo "Done","\n";

 

七:定制化错误处理的缺点
根据手册,如下错误类型没法使用定制化的方法进行处理:
E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING
在调用set_error_handler()方法的地方会发起E_STRICT报错。
由于定制化错误处理是处理运行时错误,以上错误同时存在会致使set_error_handler()方法没法被定义。因此一个自定义的错误处理方法没法在同一个文件里同时处理这些错误。
许多初学者,甚至中级开发者,想要在定制化错误处理方法中记录这些错误。虽然没有什么能够阻止你这样作,可是上面的警告明确告诉你这样不会捕捉到你系统中全部的错误,同时监控全部的错误日志也是很重要。框架

八:检查错误处理程序
由于没有get_error_handler方法,因此你没法得知一个错误是否已经存在相应的错误处理程序。因此你须要一个比较尴尬的方式来获取你须要的信息。
当你设置一个错误处理程序的时候:

$result = set_error_handler(array('Valid', 'callback'));

 

返回值就是你将要替换掉处理器的方法名。若是以前不存在这样的一个处理程序,返回结果是NULL。幸运的是,restore_error_handle方法容许你重置最近一次的set_error_handler方法调用。

九:异常 Exception
PHP中未被捕捉的异常会建立一个E_ERROR错误,并且PHP会停止运行。警告:这一未被捕捉的异常没法被定制的错误处理器处理。
事实上,能够采用set_exception_handler来监听未被捕捉到到异常:

function ourMagicExceptionHandler($e)
{
    echo 'Someone threw an exception (type: <code>' . 
    get_class($e) . '</code>) and no one caught it.';
    return true;
}    
set_exception_handler('ourMagicExceptionHandler');
throw new Exception("Foo");
echo "Done";

可是,虽然你使用这种方法捕捉到了异常,你的程序仍是会在定制化处理器执行结束以后中止运行。

十:Runtime VS. php.ini
许多控制错误的配置能够在php.ini或者在error_reporting or ini_set里面设置,可是你偶尔仍是会发现一些奇怪的行为可是却没有PHP错误。由于PHP处理错误的方法随时会改变,你永远没法确保你看到了全部的错误。
像以前提到的,许多处理这种状况的方法是在代码里临时添加以下代码:

error_reporting(E_ALL | E_STRICT); 
ini_set('log_errors','1');
ini_set('error_log','/tmp/my-custom-php-error-log.log');
ini_set('display_errors', '1');

 然而这样并非万无一失。PHP容许管理员禁用一些方法。许多服务器管理商会出于安全的考虑禁用 error_reporting 和 init_set 方法。除了这些功能,还有一些公开或者私有的PHP安全扩展,会限制咱们能或者不能添加一些运行时设置。

若是你是一个php开发,这是一些你须要了解的细节。

十一:查找php.ini文件

有时当你在你不熟悉的系统查找php.ini文件的时候会很是的困难。这是由于PHP会加载多个ini文件。PHP的ini文件的位置是在编译的时候就设置
好的。除了主要的设置文件php.ini 文件,php还会查找以ini结尾的其余配置文件,并在php.ini文件以后加载。
幸运的是,PHP有一种机制能够展现这些ini文件的列表。若是你在命令行里运行PHP,只须要在后面添加--ini标记:

$ php --ini
Configuration File (php.ini) Path: /usr/local/php5/lib
Loaded Configuration File:         /usr/local/php5-20130127-205115/lib/php.ini
Scan for additional .ini files in: /usr/local/php5/php.d
Additional .ini files parsed:      /usr/local/php5/php.d/10-extension_dir.ini,
/usr/local/php5/php.d/50-extension-apc.ini,
/usr/local/php5/php.d/50-extension-curl.ini,
/usr/local/php5/php.d/50-extension-intl.ini,

你就能够获取全部加载的php.ini文件以及他们的位置。

若是你是在服务器上运行,phpinfo()会输出类似的内容:

固然,这是比较简单的状况,PHP永远没有办法如此简单
在文章的前面咱们曾提到,有些配置能够在php.ini里面设置,也能够在ini_set 方法里面设置。也能够在服务器的配置文件里面作些设置。
假设你在使用Apache服务器,意味着在httpd.conf 和.htaccess使用以下语法:

php_value display_errors 1

除此以外,PHP5.3引入了.user.ini文件。这一系统容许你在服务器目录下建立.user.ini文件,php会解析这些文件获取ini的值。虽然以ini结尾,这个文件的格式和.htaccess的格式是一致的。

最后,虽说不是严格意义上的ini文件,PHP有一个ini配置文件名为auto_prepend_file。这一配置,容许你在php.ini主文件解析以前添加并解析文件。我曾碰到过多用户配置各自的auto_prepend_file来加载各自的运行时设置。若是这一设置路径未包含全路径,PHP会在include_path里查找该文件。

十二:定制PHP错误信息
PHP有一个方法你能够调用来触发本身的报错信息,这些信息默认是E_USER_NOTICE级别,你能够经过改变第二个参数来改变错误级别。

trigger_error('This is a custom notice.',E_NOTICE);

 十三:其余错误日志
还有另外两个错误记录方法程序员须要了解的:error_log 和 syslog。
根据手册,error_log方法“发送错误到指定的错误处理路径”。这并不意味这PHP会报错。若是你是在web中访问,错误会被直接发送到error log.若是你是在命令行模式下调用 error_log 方法,也会发送错误信息到error log,除非error log 没有设置。若是error log ini没有设置,命令行PHP会发送信息到标准错误输出。
error_log方法总会执行它的职责,不管log_errors ini是否有设置。所以,error_log常常被框架用来确保信息被传送到error log。即便会忽略log_errors的设置,error_log方法会按照error_log ini的设置指定一个文件位置(若是error_log未设置,默认指向web服务器日志)。
syslog方法与error_log 相似,会直接发送一条信息到日志系统。然而,它并非发送信息php日志或者网络服务器日志,而是直接发送到操做系统到系统日志。若是想了解更多信息,请查看手册页面:

$ man syslog.conf

你一般会看私人框架中开发者同时是系统管理员到状况下看到这种操做,这样一般是为了让全部到日志同时出如今一个地方,方便查阅。大部分
Modern PHP开发更倾向把本身框架的系统独立于特定的系统像 *nix‘s syslogd。

十四:eval方法中的错误(Errors During eval
像许多“终端开发不须要编译东西同样”,PHP语言有一个eval方法。eval方法容许用户建立一个字符串类型的PHP代码块,而后像一个小程序同样能够运行。有一些出于安全的考虑使eval在开发圈中成为一种热门话题。咱们在此不作讨论。有些错误的w/r/t你须要记住。
PHP主程序中的eval块里面的代码在出现错误的时候也会经过set_error_handler方法把错误发送到定制到错误处理器中。然而,当PHP为eval块里面到错误建立错误信息的时候,错误信息里面的行号是eval块里面的行号,而不是PHP主程序里面的行号。好比:
 

<?php    
echo "Foo";
echo "Baz";
eval('echo $foo;');

will issue the following error message

PHP Notice:  Undefined variable: foo in /path/to/example.php(4) : eval()'d code on line 1

错误里面的line1是指eval里面代码块的第一行,而不是PHP代码的第一行。若是你像知道eval错误是在PHP主程序中在第几行,请查找修饰语(这里是4)
另外,还记得定制化错误处理器不能够处理同一文件中特定类型的错误吗(像E_PARSE)?这一规则在eval中一样适用。


十五:最近的错误(The last error) $php_errormsg
就像以前提到的,PHP能够从不少中错误类型中恢复。处理完一个错误以后,PHP会把错误信息填充到当前做用域中一个叫 $php_errormsg到变量中,以确保$php_errormsg老是可以拿到最近到一条错误信息(除非你离开了当前做用域)。我看到许多定制错误处理器用到了这一变量,因此或许你想了解下这个变量。
提示:php.ini中track_errors参数为true时这一变量才会被使用。

十六:错误控制操做符(The Error Control Operator)

PHP有一个错误控制/抑制运算符。把这一运算符放在任何一段可能出错到PHP代码以前,PHP会吞掉全部到错误。好比运行如下代码本应该抛出一个为定义变量到异常(undefined variable foo Notice):

function main()
{
    echo $foo;
}
@ main();

可是由于以前加了@符号,没有产生任何错误。不行的是,错误仿佛彻底被吞掉了,既不会被显示,又不会被记录。追踪错误出现的惟一途径是以前提到的$php_errormsg。因此,理论上来说,被抑制的报错仍是有办法经过$php_errormsg来获取到的。可是考虑到$php_errormsg只做用于错误发生的做用域,因此没有额外的编码是没法直接获取错误所发生的具体位置。因此这种方法的做用仍是被限制的。
大多数专业的我所知道和尊重的PHP开发都会尽量避免使用@符号。可是由于有时候一个极小的错误能够经过@符号轻易的避免,可是可能却要花费一天的时间也没法追踪到。总之,不到万不得已不要使用@符号。

十七:Backtrace
虽然不是严格意义上的错误处理机制,debug_backtracedebug_print_backtrace常常被用在定制错误处理器中输出PHP调用堆栈。PHP堆栈会列出到达一个特定深度/节点的所又途径/方法--都是些有用的调试信息。
可是因为可能出现信息量过大的状况,致使堆栈输出吃掉因此内存,因此你可能须要一个设置来控制输出节点的深度:

xdebug.var_display_max_depth = 3

文章来源:
https://alanstorm.com/php_error_reporting/

相关文章
相关标签/搜索