PHP最基本的调试策略是使用PHP的错误报告机制,通过它来找到代码中的语法错误,通过执行程序的结果来迅速查找到程序中的逻辑错误。也可以在脚本中插桩,输出某些变量的值,观察程序运行状态。
PHP报告
通常在一个PHP脚本中发生错误时,出错信息会被插入到当前脚本进行输出,如果是致命的错误,脚本就会终止执行。
PHP将脚本错误分成3个等级,提示(notice)、警告(warning)、错误(error)。
Notice信息可能是脚本运行错误导致的,也可能只是在正常运行过程中出现的。实际上这些也许就是代码中的缺陷,因为PHP对其解释可能与代码的本意有所不同。
Warning标记着一个非致命性的错误,在代码运行时产生。它们并不是致命的错误,不会停止脚本的执行。
Error消息说明出现了致命的错误,会导致脚本停止运行。PHP运行的任何阶段都可能产生这种错误,包括初始化,解析和执行代码阶段。
2、设置php.ini文件中的错误处理机制
使用PHP的错误报告是调试程序的基础。通过对PHP配置文件的设置,使用程序在执行过程中自动抛出错误的代码行,帮助开发者发现并消灭错误。但当程序调试结束和测试成功后,就要关闭错误报告机制,避免浏览者看到一些错误信息。
PHP的调试是繁琐的,需要修改PHP.ini中的报错相关的设置,这样当PHP代码再有语法错误时,就会在页面上显示出错信息,具体设置如下:
Display_errors=off
Error_reporting=e_all
调成:
Display_errors=on;将错误信息显示在页面上
error_erporting=e_all& ~e_notice
Display_errors变量告知PHP是否显示错误。默认值是OFF。但要让开发过程更加轻松,需要把这个值设为ON,以便进行程序调试。
Error_reporting变量的默认值是E_all,这个设置示从“不良编码实践”、“无害提示”、“出错”的所有信息。E_all值的设置对于开发过程来讲过于细化。通常只需要设置错误提示和显示不良编码即可,因此,需要把这个值设置为e_all &~e_notice.设置完成之后,保存php.ini文件,然后重新启动apache服务器即可。
通过这些错误设置,开发者就能够在执行程序过程中,输出错误,找到其中的缺陷。可以在浏览器中查看到错误信息,以及显示出错代码的行号,并分析产生错误的原因。
4、使用@前缀字符屏蔽PHP脚本错误提示
前缀字符@不是一个命令,而是dos批处理的一个特殊的标记符,是命令行回显屏蔽符。
前缀字符@表示执行时本行在cmd里面不显示,可以使用echo off关闭显示,仅用于屏蔽命令行回显。在默认情况下,当PHP代码遇到错误时会显示错误信息,包括当前脚本的绝对路径,这样会造成一些不安全的因素,可以在调用函数时加上前缀字符@,以屏蔽错误信息。
错误处理记录日志
一般情况下,在开发一个网站时,为了调试方便,我们希望错误直接显示在页面上。但当某个产品投入使用,那么第一件事就是应该将display_errors选项关闭,以免因为这些错误所透露的路径、数据库连接、数据表等信息而遭到黑客攻击。为了不能把内部的错误信息显示给访问者,最佳的方法是记录到错误日志中。这时,需要在php.ini文件中修改如下设置:
display_errors=off
log_errors=on;开启错误日志功能
error_log=/tmp/php_errors.log;设置错误日志路径
如下一个php脚本
[root@localhost~]# vi testphp.php
$time= strtotime($argv[1]);
$date_start= date('Y-m-d 00:00:00', $time), //语法错误处
echo$date_start;
?>
运行如下
[root@localhost~]# php testphp.php 20190701
[root@localhost~]# cat /tmp/php_errors.log
[11-Jul-201904:06:33 UTC] PHP Parse error: syntaxerror, unexpected ',' in /root/testphp.php on line 4
[root@localhost~]#
可见设置了错误输入日志,脚本运行中的异常信息不会再输出到标准输出了,而是记录到了我们设置的错误日志中。
另外也可以设定error_log = syslog,使这些错误信息记录到操作系统的日志里。
PHP设置文件php.ini中明明已经设置display_errors = Off,但是在运行过程中,网页上还是会出现错误信息。经查log_errors= On,据官方的说法,当这个log_errors设置为On,那么必须指定error_log文件,如果没指定或者指定的文件没有权限写入,那么照样会输出到正常的输出渠道,那么也就使得display_errors 这个指定的Off失效,错误信息还是打印了出来。于是将log_errors = Off,问题就解决了。
除了上述的错误日志记录,PHP提供了内建的错误处理函数error_log(),可以传入自定义的消息信息。它的原型为
bool
error_log ( string message [, int message_type [, string destination [, string
extra_headers]]] );发送一个错误信息到Web服务器的错误日志,一个TCP的端口或者是一个文件
第一个参数message是消息内容,第二个参数type是消息类型,第三个参数是目标文件,第四个参数是其他的头信息。其实一般第四个参数都用不到,我们主要看前面三个参数,第二个参数是消息类型,包括0, 1, 2, 3等四种类型,0是默认的类型。四个类型的作用:
0:信息内容发送到PHP的系统日志记录,使用操作系统的自己的日志记录机制或一个文件,整个取决于php.ini中的配置选项error_log的内容。这是缺省选项。
1:把信息内容发送到一个邮件地址,第三个参数就是一个邮件地址,第四个参数是一个头信息发送邮件的,第二个类型使用mail()函数来发送邮件
2:消息通过PHP的调试服务器,远程的写入到某个PHP调试服务器上,当然,PHP在编译的时候--enable-debugger必须打开,另外,整个类型只是针对PHP 3有效
3:消息作为一个新行附加在一个目标文件中
其实对于我们来说,日志为了简便起见,一般直接使用类型3就比较合适了,我们在脚本语句中显式插入这个函数,跟踪程序运行过程,如
$time= strtotime($argv[1]);
$date_start= date('Y-m-d 00:00:00', $time);
error_log("beginprint date_stat",3,'php_error.log');
echo$date_start;
?>
使用error_log函数,和配置文件中的配置log_errors没有关系。如果没有指定输入日志的绝对路径,则在当前解释器工作目录下创建文件。
使用打印函数
这些函数包括echo、print、printf()、print_r()、var_dump()。
echo实际上不是一个函数,是php语句,因此您无需对其使用括号。所以echo并不返回值,不能使用它来赋值。注意不要使用echo输出一个数组,这样它输出只是变量的类型,如
[root@localhost~]# vi testphp.php
$company_array=array(
'switch'=>"hua_wei",
'itm'=>"netsec",
'router'=>"H3C"
);
echo$company_array;
?>
效果如下
[root@localhost~]# php testphp.php
Array
print和 echo 用法一样,它也不是一个函数,因此无需对其使用括号。
print_r()函数打印关于变量的易于理解的信息。原型
mixed print_r ( mixed $expression [,bool return ] )
如果变量是string , integer or float , 将会直接输出其值,如果变量是一个数组,则会输出一个格式化后的数组,也就是有key和value对应的那种格式。print_r有两个参数,第一个是变量,第二个可设为true,如果设为true,则会返回一个字符串。
[root@localhost~]# vi testphp.php
$company_array=array(
'switch'=>"hua_wei",
'itm'=>"netsec",
'router'=>"H3C"
);
print_r($company_array);
$arrstr=print_r($company_array,True);
echo$arrstr;
?>
运行结果
[root@localhost~]# php testphp.php
Array
(
[switch] => hua_wei
[itm] => netsec
[router] => H3C
)
Array
(
[switch] => hua_wei
[itm] => netsec
[router] => H3C
)
如果需要知道变量的类型,可以使用var_dump()函数。它显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开值,通过缩进显示其结构。如
将print_r($company_array)替换为var_dump($company_array)则运行结果如下
array(3){
["switch"]=>
string(7) "hua_wei"
["itm"]=>
string(6) "netsec"
["router"]=>
string(3) "H3C"
}
var_dump和print_r的区别:var_dump返回表达式的类型与值,而print_r仅返回结果,相比调试代码使用var_dump更便于阅读。
file_put_contents函数
上节介绍的打印函数通常会将输出信息打印在标准输出上,我们可以将程序运行的状态信息输出到其他外部文件中,便于后续追踪。通过使用file_put_contents函数即可实现,形如
file_put_contents('filepath/filename.txt',print_r($var, true));
print_r将变量(字符串、多维数组等)作为一个字符串整体输出,因此可以结合这个函数使用。将print_r函数的返回值输出到外部文件中。
centos下file_put_contents()无法写入文件的原因可能是文件没写入权限,chmod追加权限即可。
网友评论