php错误处理面试,PHP 核心特性 - 错误处理

错误与异常

错误,可以理解程序本身的错误,例如语法错误。而异常则更偏向于程序运行不符合预期或者不符合正常流程;对于 PHP 语言而言,处理错误和处理异常使用的机制完全不同,因此很容易让人产生困惑。

例如,我们希望通过捕获异常来处理除数为 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 示例 - 引入不存在的文件

$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

示例

// 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 = On

display_startup_error = On

error_reporting = -1

log_errors = On

生产环境推荐配置

display_errors = Off

display_startup_error = Off

; 报告 Notice 以外的所有错误

error_reporting = E_ALL & ~E_NOTICE

log_errors = On

Symfony 编码规范相关

异常和错误消息字符串必须使用sprintf来进行拼接;

throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));

当错误类型为E_USER_DEPRECATED时,需要添加@

@trigger_error("foo", E_USER_DEPRECATED);

以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要戳这里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值