PHP开发基础教程之Error
一、问题引入
在之前我们在写代码的时候经常会看到:函数名写错了,忘加分号了,函数被重新定义了都会报各种不同样的错。
在开发中,显示错误对我们的开发非常有利。因为,显示错误后能帮我们快速定位错误、解决问题。
而在生产环境(即公网)给其他人访问的的网站、微网站、手机网站、手机接口... ...等等。
如果错误显示出来了,就容易暴露:
服务器的文件路径和文件存储规范
有些人喜欢用个人名命名,通过社会工程学可以反向推理出密码
有时还会暴露mysql数据库服务器的地址
... ... 等等
上面这些信息特别容易被网上别有用心的一些人给利用。
例如下面这段代码,我们不加分号就全面暴露了我们的服务器端文件存放路径、框架信息等。如下:
<?php $fp = fopen('abc.txt','a+') fwrite($fp,'abc'); fclose($fp); ?>
报错了:
错误提示中文翻译过来为:
解析错误:语法错误。意外发生在/home/vagrant/Code/Laravel/public/index.php 文件的第5行fwrite附近。
在本章中,我们来尝试解决这个问题
二、禁止显示错误
在php.ini配置文件中。我们可以控制php的错误显示状态。
php.ini中有一个专门的配置项:
display_errors
这个选项设置是否将错误信息输出到网页,或者对用户隐藏而不显示。
这个值的状态为on 或者 off,也可以设值为1 或者0。
display_error的值设为0或者off则不在页面中显示错误,如果设为1或者on则显示错误信息。
问题:如果没有修改服务器php.ini的状态权限怎么办?
可以使用ini_set。
<?php ini_set('display_errors' , 0 ); ?>
上面的代码也相当于修改了php.ini中display_errors的值。不过,仅仅在当前php代码中生效。
问题:想取得php.ini的配置项状态怎么办?
可以使用ini_get(参数项) 得到参数的值。
实例:
<?php echo '服务器中display_errors的状态为' . ini_get('display_errors'); ?>
注:修改完php.ini文件,需要重启服务器。
三、错误报告级别
1.错误类型
php大家最常见的错误显示:
在上面的几种类型中:
error最严重,必须要解决。不然程序无法继续向下执行
warning也很重要。通也必须要解决。如果明确的,故意的可以不用处理。
notice 你可以不用管。但是在有些公司,项目标准特别高。在高标准要求的项目中也必须要解决。因为,notice会影响到PHP的执行效率。通常发生在函数未定义等。
parse错误,是指语法错写错了,必须要解决
代表全部类型的所有错误
其它根据上面扩展出来的另外一些需要了解的错误项:
在学习过程中,上面的类型了解即可。因为基本不会遇到,遇到了大家查一下本书或者查一下手册就清楚了。
2.error_reporting 报告错误类型
error_reporting 是指错误报告。在php.ini中也有这样一个参数。这个参数。决定了PHP引擎记录、报告、显示哪些错误类型。
1)、 在php.ini中error_reporting参数。
如若error_reporting参数设置为0。整个PHP引擎发错误均不会显示、输出、记录。在下一章将要讲到的日志记录中,也不会记录。
如果我们想显示所有错误可以写上:
error_reporting = E_ALL
想要显示所有错误但排除提示,可以将这个参数写为:
error_reporting = E_ALL & ~ E_NOTICE
显示所有错误,但排除提示、兼容性和未来兼容性。可写为:
error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
2)、在有些情况下我们无权限操作php.ini文件,又想要控制error_reporting怎么办呢?
在运行的xxxx.php文件中开始处,我们可以使用error_reporting()函数达到目标。
演示代码如下:
<?php //关闭了所有的错误显示 error_reporting(0); //显示所有错误 //error_reporting(E_ALL); //显示所有错误,但不显示提示 //error_reporting(E_ALL & ~ E_NOTICE); ?>
上面的代码你可以试试,故意写错代码看看。在当前文件中还会不会显示指定的错误。
[扩展、了解知识点]: @ 符是我们之前学习过的单行不显示错误,请不用或者少用@符。
我们拿读取一个不存在的文件,这样的php代码来演示实现过程:
<?php //读取一个不存在的adsaf.txt文件,用@符抑制错误 @$fp = fopen('adsaf.txt','r'); ?> @符效率较低,它在php内核中的实现过程是: <?php //关闭错误 error_reporting(0); //读取一个不存在的文件,显示错误 //显示错误 error_reporting(E_ALL & ~ E_NOTICE); ?>
四、错误记录日志
在一些公司里面,有专门的日志收集系统。日志收集系统会在背后默默的帮你收集错误、警告、提示。
也有些公司没有专门的日志收集系统,通过文件来服务器当中的运行日志。
其中:PHP的错误,警告这些是必须要收集的。
那么问题来了——不让用户看到,设置好错误报告级别好,如何将错误收集到日志系统中呢?
这里有需要使用到php.ini的相关配置项。这两个配置项为:
说明:
在表格中的log_errors和log_errors_max_len非常好理解。
而error_log 指定将错误存在什么路径上。配置项中的syslog可能有点不太好理解。syslog是指系统来记录。windows系统在电脑的日志收集器里面。linux默认在:/etc/syslog.conf
[扩展] 了解知识点。若Linux系统启动或修改了日志收集。可能存储在第三方专用的日志收集服务器中。
此外,PHP还为我们专门准备了一个自定义的错误日志函数:
bool error_log ( string $错误消息 [, int $错误消息类型 = 0 [, string $存储目标]] )
这个函数可以把错误信息发送到web服务器的错误日志,或者到一个文件里。
常用的错误消息类型:
示例:
<?php //无法连接到数据库服务器,直接记录到php.ini 中的error_log指定位置 error_log("无法连接到数据库服务器服务器"); //可以发送邮件,但是php.ini必须配置过邮件系统 error_log('可以用邮件报告错误,让运维人员半夜起床干活',1 ,'liwenkai@phpxy.com'); //记录在指定的位置 error_log("我是一个错误哟", 3, "d:/test/my-errors.log"); ?>
注:
error_log 中发送邮件可能对初学者不熟,您可以不用掌握些块知识。
五、自定义错误处理函数
这一块知识起点有些高。大多数人没有软件工程、自定义错误处理的经验,很难想象出使用的场景。若你想跳过此块的学习,完全可以,并且我们支持。
此块知识点对于实际应用中应用场景不多。如果,有计划开始要自己写框架时、或者您做完了本书的第一个项目。
用户自定义错误经常用到的两个函数:
set_error_handler ( callable $回调的错误处理函数)
设置一个用户定义的错误处理函数
trigger_error ( string $error_msg)
产生一个用户级别的 error/warning/notice 信息
<?php //定义一个自定义的错误处理函数 function customError($errno, $errstr, $errfile, $errline) { //输出错误消息 echo "<b>Custom error:</b> [$errno] $errstr<br />"; //输出错误文件和错误行 echo "Error on line $errline in $errfile<br />"; echo "Ending Script"; //中止程序运行 exit; } //使用set_error_handler 绑定用户自定义函数 set_error_handler("customError"); $test=2; //触发自定义错误 if ($test > 1) { trigger_error("A custom error has been triggered"); } ?>