例如,我们希望通过捕获非常来处理除数为 0 的情形,但是在捕获到非常之前,PHP 就触发了缺点。
try { $a = 5 / 0;} catch (Exception $e) { $e->getMessage(); $a = -1; // 通过非常来处理 $a 为 0 的情形,但是实际上,捕获不到该非常}echo $a;// PHP Warning: Division by zero
也便是说,PHP 将除数为 0 的情形当成了缺点而触发,而不会自动抛出非常,因此没法捕获。类似的,在很多情形下,PHP 都没办法自动抛出非常。只能通过 if - else 语句判断再结合 throw 方法来并手动抛出非常。
上述情形的发生,紧张还是由于非常机制是 PHP 向面向工具演进后得到的产物。而在此之前 PHP 的报错紧张还是通过缺点机制,因此,在很多情形下,PHP 的缺点要比非常更有代价。不过 PHP7 开始统一这两者,使缺点也可以像非常那样抛出(这部分内容将放在非常部分讲解)。
缺点级别
PHP 中的缺点可理解为 使脚本不运行不正常的情形,根据缺点级别从高到低可划分为五类
Parse error 或 Syntax Error - 语法解析缺点,触发该缺点后,脚本完备无法运行;Fatal Error - 致命缺点,触发该缺点后,后面的脚本无法连续实行;Warning Error - 涌现比较不恰当的地方,脚本可连续实行;Notice Error - 涌现不恰当的地方,但是程度比 Warning Error 低,脚本可连续实行;Deprecated Error - 不推举这么利用,未来可能会废弃,脚本可连续实行;默认情形下,PHP 触发缺点,并显示缺点的级别及对应的提示。
Parse Error 示例 - 语句结尾不写分号
echo "abc"// PHP Parse error: syntax error, unexpected end of file, expecting ',' or ';
Fatal Error 示例 - 利用不存在的函数
echo "before\n";foo();echo "after"; // 本行无法连续实行// before// PHP Fatal error: Uncaught Error: Call to undefined function foo()
Warning Error 示例 - 引入不存在的文件
点击「社区福利」30G-PHP进阶资料,助力大家达到30K
$a = "foo";include('bar.php');echo $a; // 程序连续实行// PHP Warning: include(bar.php): failed to open stream: No such file or directory ...// foo
Notice Error 示例 - 输出不存在的变量
echo $foo;echo 12345;// PHP Notice: Undefined variable: foo// 12345
Deprecated Error 示例 - 在一些字符串函数中传入数字而非字符串
strpos('12345', 3);// PHP Deprecated: strpos(): Non-string needles will be interpreted as strings in the future
除了默认触发外,用户也可以利用 set_error_handler 函数自定义缺点处理,大多数缺点类型都可以进行自定义处理,除了 E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING 外。
set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRICT ] ) : mixed
示例
<?php// E_ALL - 处理全部缺点类型set_error_handler('customError', E_ALL);/ @param int $errno 缺点的级别 @param string $errstr 缺点的信息 @param string $errfile 缺点的文件名(可选) @param string $errline 缺点发生的行号(可选) /function customError(int $errno, string $errstr, string $errfile, string $errline){ echo sprintf('缺点为 %s', $errstr);}$a = 5 / 0; // 缺点为 Division by zero
用户也可以通过 trigger_error 函数来手动触发一个用户级别的缺点(E_USER_ERROR、E_USER_WARNING、E_USER_NOTICE、E_USER_DEPRECATED)。
function division($a, $b) { if($b == 0){ @trigger_error("0 不能作为除数", E_USER_NOTICE); return -1; } return $a / $b;}echo division(10, 0);
一些缺点处理干系的常用配置
error_reporting - 设置缺点的报告级别display_errors - 是否显示缺点display_startup_error - 是否显示 PHP 启动过程中的显示log_errors - 设置是否将脚本运行的缺点信息记录到做事器缺点日志或者 error_log 之中《Modern PHP》提出了四个规则
一定要让 PHP 报告缺点;在开拓环境中要显示缺点;在生产环境中不能显示缺点;在开拓环境和生产环境中都要记录缺点;开拓环境推举配置
display_errors = Ondisplay_startup_error = Onerror_reporting = -1log_errors = On
生产环境推举配置
display_errors = Offdisplay_startup_error = Off; 报告 Notice 以外的所有缺点error_reporting = E_ALL & ~E_NOTICElog_errors = On
非常和缺点字符串必须利用 sprintf 来进行拼接;
throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));
当缺点类型为 E_USER_DEPRECATED 时,须要添加 @
@trigger_error("foo", E_USER_DEPRECATED);
参考资料
PHP Errors: 4 Different Types (Warning, Parse, Fatal, and Notice Error)PHP: 预定义常量 - ManualPHP 核心技能与最佳实践 (豆瓣)PHP: 运行时配置 - ManualPHP 规范 - Symfony 代码规范 | PHP 技能论坛