PHP7语言基础——错误和异常处理

常见的错误和异常

  1. 拼写错误
    PHP中常量和变量都是区分大小写的,如果将常量或变量名写错,将会得到一个**Notice**: Undefined variable:提示。
    PHP中的函数名、方法名、类名是不区分大小写的,但是建议使用与定义时相同的名字。
    PHP中的魔术常量不区分大小写,但是建议全部大写。
    另外,在编写代码过程中,由于输入法的原因,还容易导小括号,分号,引号等出现错误,因此要特别小心。

  2. 单引号和双引号混用
    单引号、双引号在PHP中没有特殊区别,都可以用来创建字符串。但必须成对儿出现,另外缺少单引号或者双引号也是经常出现的问题。系统会抛出一个**Parse error**: syntax error,错误。

  3. 括号使用混乱
    当编写的代码括号的层次较多时容易出现缺少反括号的错误。系统会抛出一个**Parse error**: syntax error错误

  4. 相等运算符与赋值符号混淆
    在进行相等比较的时候容易产生此类错误。此类错误多数情况下不会抛出异常,但是会导致程序功能与开发者意图相悖。

  5. 缺少美元符号
    在PHP中,设置变量时需要使用美元符号,如果不添加美元符号就会引起解析错误,**Parse error**: syntax error

  6. 调用不存在的常量和变量
    调用没有声明的变量或常量,将会触发**NOTICE: Undefined variable**错误。

  7. 调用不存在的文件
    调用不存在的文件,将会触发**Warning**错误。如:

    Warning: include(mybook.php): failed to open stream: No such file or directory 
    Warning: include(): Failed opening 'mybook.php' for inclusion (include_path='.;C:\php\pear') in
    
  8. 环境配置错误
    环境配置不当也会给运行带来错误,例如PHP配置文件和PHP的版本等,如果配置不正确,就会提示文件无法打开、操作权限不具备和服务器无法连接等错误信息。

错误处理

常见的错误处理方法包括使用错误处理机制、使用DIE语句调试、自定义错误和错误触发器等。

php.ini中的错误处理机制

php.ini文件规定了错误的显示方式,包括配置选项的名称、默认值和表述的含义等。常见的错误配置选项内容如下:

名称默认值含义
display_errorsOn设置错误作为PHP的一部分输出。开发的过程中可以采用默认的设置,但为了安全考虑,在生产环境中还是应设置为Off。
error_reportingE_ALL这个设置会显示所有的出错信息。这种设置会让一些无害的提示也显示,所以可以设置error_reporting的默认值为error_reporting=E_ALL&~E_NOTICE,这样只会显示错误和不良编码
error_lognull设置记录错误日志的文件。默认情况下降错误发送到web服务器日志,用户也可以指定写入的文件
html_errorsOn控制是否在错误信息中采用HTML格式
log_errorsOff控制是否应该将错误发送到主机服务器的日志文件
display_startup_errorsOff控制是否显示PHP启动时的错误
track_errorsOff设置是否保存最近一个警告或错误消息

应用DIE语句调试

使用DIE语句调试的优势是,不仅可以显示错误的位置,还可以输出错误信息。一点出现错误,程序会终止运行,并在浏览器上显示出出错之前的信息和错误信息。

【示例】

<?php
echo "这是程序出错之前的信息<br />";
if (!file_exists("test.txt")) {
	die("文件不存在");
} else {
	$file=fopen("test.txt");
}
echo "<br />这是程序出错之后的信息";
?>

程序输出结果:

在这里插入图片描述

可以看到,使用DIE语句调试在错误之后便终止了脚本执行。

自定义错误和错误触发器

用户可以通过创建专用函数error_function(),来在PHP发生错误时调用该函数。该函数的语法格式如下:

error_function(error_level, error_message, error_file, error_line, error_context)

创建该函数必须至少包含error_level和error_message两个参数,函数各参数的含义如下:

  • error_level:必需参数,为用户定义的错误定义错误报告级别,必须是一个整数。
  • error_message:必需参数,为用户定义的错误定义错误消息。
  • error_file:可选参数,定义错误在其中发生的文件名
  • error_line:可选参数,定义错误发生的行号
  • error_context:可选参数,定义一个数组,包含当错误发生时在用的每个变量以及它们的值。

error_level的值和含义如下表:

数值常量含义
2E_WARNING非致命的run-time错误,不暂停脚本执行
8E_NOTICERun-time通知,脚本发现可能有错误发生,但也能在脚本正常运行时发生
256E_USER_ERROR致命的用户生成的错误,类似于程序员使用PHP函数trigger_error()设置的E_ERROR
512E_USER_WARNING非致命的用户生成的警告,类似于程序员使用PHP函数trigger_error()设置的E_WARNING
1024E_USER_NOTICE用户生成的通知,类似于程序员使用PHP函数triger_error()设置的E_NOTICE
4096E_RECOVERABLE_ERROR可捕获的执行错误,类似E_ERROR,但可被用户定义的处理程序捕获
8191E_ALL所有错误和警告

【示例】

<?php
// 首先自定义错误处理函数
function customError($errno, $errstr) {
	echo "<b>错误:<b> [$errno] $errstr<br />";
	echo "终止程序";
	die();
}
// 然后使用set_error_handler()来设置自定义错误处理函数
// set_error_handler(error_function, error_types)
// error_types参数可选,默认为E_ALL
set_error_handler("customError");

// 触发自定义错误函数
echo($test);
?>

程序输出结果:

在这里插入图片描述

在脚本中用户输入数据的位置,当用户输入无效时触发错误。在PHP中,这个任务由trigger_error()完成。

trigger_error()函数创建用户自定义的错误消息。用于在用户指定的条件下触发一个错误消息。它与内建的错误处理器一同使用,也可以由set_error_handler()函数创建的用户自定义函数一起使用。如果指定了一个不合法的错误类型,该函数返回false,否则返回true。

trigger_error()函数的具体语法格式如下:

trigger_error(error_message, error_types)

其中,error_message参数为必需参数,定义错误消息,长度限制为1024个字符。error_types为可选参数,定义错误消息的错误类型,可能的值为E_USER_ERROR、E_USER_WARNING、E_USER_NOTICE。

【示例】

<?php
$test = 5;
if ($test > 4) {
	// 创建自定义错误消息
	trigger_error("value must be 4 or below");
}
?>

程序输出结果:

在这里插入图片描述

【示例2】

<?php
// 定义错误函数
function customError($errno, $errstr) {
	echo "<b>错误:</b> [$errno] $errstr";
}

// 设置错误处理函数
set_error_handler("customError", E_USER_WARNING);

// trigger_error函数
$test = 5;
if ($test > 4) {
	trigger_error("Value must be 4 or below", E_USER_WARNING);
}
?>

程序输出结果:

在这里插入图片描述

错误记录

默认情况下,根据php.ini中的error_log配置,PHP向服务器的错误记录系统或文件发送错误记录。通过使用error_log()函数,用户可以向指定的文件或远程目的地发送错误记录。

error_log()函数语法格式如下:

error_log(string $message[, int $message_type=0[, string $destination[, string $extra_headers]]]):bool

函数参数说明:

  • message:应该被记录的错误消息。
  • message_type:设置错误应该发送到何处。可能有以下信息类型:
    • 0:发送到PHP的系统日志,使用操作系统的日志机制或者一个文件,取决于error_log指令设置了什么。这是默认选项。
    • 1:发送到参数destination设置的邮件地址。第四个参数extra_headers只有在这个类型里才会被用到。
    • 2:不再是一个选项
    • 3:被发送到位置为destination的文件里。字符message不会默认被当做新的一行。
    • 4:直接发送到SAPI的日志处理程序中。
  • destination:目标。它的含义描述于以上,由message_type参数所决定。
  • extra_headers:额外的头。当message_type设置为1时使用,该信息类型使用了mail()的同一个内置函数。

警告:error_log()并非二进制安全的。null字符可能截断。

【示例】

<?php
// 定义错误函数
function customError($errno, $errstr) {
	echo "<b>错误:</b> [$errno] $errstr<br />";
	echo "错误记录已经发送完毕";
	error_log(" 错 误:[$errno] $errstr", 1, "someone@example.com", "From:webmastere@example.com");
}

// 设置错误处理函数
set_error_handler("customError", E_USER_WARNING);

// trigger_error函数
$test = 5;
if ($test > 4) {
	trigger_error("Value must be 4 or below", E_USER_WARNING);
}
?>

程序输出结果:

在这里插入图片描述

同时,在指定的someone@example.com邮箱中也将收到同样的信息。

异常处理

异常和错误不同,异常(Exception)用于在指定的错误发生时改变脚本的正常流程。用户可以捕获异常并做出相应处理。

异常类

PHP提供了一个异常类Exception,是所有异常类的基类。

Exception {
	/* 属性 */
	protected string $message;
	protected int $code;
	protected string $file;
	protected int $line;
	
	/* 方法 */
	public __construct([string $message = "" [, int $code = 0 [, Throwable $previous = NULL ]]])
	final public getMessage( void ): string
	final public getPrevious( void ): Throwable
	final public getCode( void ): int
	final public getFile( void ): string
	final public getLine( void ): int
	final public getTrace( void ): array
	final public getTraceAsString( void ): string
	public __toString( void ): string
	final private __clone( void ): void
}

关于该类中属性和方法的说明如下:

属性:

  • message:异常消息内容
  • code:异常代码
  • file:抛出异常的文件名
  • 抛出异常在该文件中的行号

方法:

  • Exeption::__construct:异常构造函数
  • Exeption::getMessage:获取异常消息内容
  • Exeption::getPrevious:返回异常链中的前一个异常
  • Exeption::getCode:获取异常代码
  • Exeption::getFile:创建异常时的程序文件名称
  • Exeption::getLine:获取创建的异常所在文件中的行号
  • Exeption::getTrace:获取异常追踪信息
  • Exeption::getTraceAsString:获取字符串类型的异常追踪信息
  • Exeption::__toString:将异常对象转换为字符串
  • Exeption::clone:异常克隆

【示例】

<?php
// 设置错误级别为0,不报错
error_reporting(0);
function theDatabaseObj() {
	$mysql = mysqli_connect('127.0.0.1', 'test', 'test', '3306');
	if($mysql) {
		return $mysql;
	} else {
		throw new Exception("Could not connect to the database");
	}
}

function db() {
	try {
		$db = theDatabaseObj();
		var_dump($db);
	} catch (Exception $e) {
		echo $e -> getMessage();
	}
}

db();
?>

程序输出结果:

Could not connect to the database

异常的基本处理方法

当异常被触发时,通常会发生以下动作:

  • 当前代码状态被保存
  • 代码执行被切换到预定义的异常处理器函数。
  • 根据情况,处理器也许会从保存的代码状态重新开始执行代码,终止脚本执行,或从代码中另外的位置继续执行。

当异常被抛出时,PHP会尝试查找匹配的catch代码块。如果异常没有捕获,而且又没有使用set_exception_handler()做相应的处理,就将发生一个严重的错误,并且输出Uncaught Exception(未捕获异常)的错误消息。

处理异常的程序通常应当包含如下几部分:

  • try代码块:可能抛出异常的代码应该位于try代码块内。若没有触发异常,则代码将照常继续执行。
  • throw代码块:这里定义如何触发异常。每一个throw必须对应至少一个catch。
  • catch代码块:catch代码块会捕获异常,并创建一个包含异常信息的对象。

自定义的异常处理器

在PHP里遇到任何错误都会抛出一个错误,很少会主动抛出异常。PHP的异常处理机制并不完善,在PHP中先处理不可预料的异常是办不到的,我们必须事先定义一些异常,将各种可能出现的异常进行if…else判断,手动抛出异常。自定义异常类的方式如下:

<?php
// 首先自定义异常类,继承Exception
class MyException extends Exception {
	public function errorMessage() {
		// 错误消息
		$errorMsg = '异常发生的行:'. $this->getLine() . ' in ' . $this->getFile() . ':<b>' . $this->getMessage(). '</b>不是一个有效的邮箱地址';
		return $errorMsg;
	}
}

// 在实际的业务代码中抛出自定义异常
$email = "someone@example.321com";
// 将可能抛出异常的代码放入try中
try {
	// 检查是否符合条件
	if (filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
		// 如果邮件地址无效,则抛出异常
		throw new MyException($email);
	}
} catch (MyException $e) {
	// 显示自定义的消息
	echo $e->errorMessage();
}
?>

程序输出结果:

在这里插入图片描述

处理多个异常

可以使用多个if…else代码块,或switch代码块,或者嵌套多个异常,使用不同的异常类,并返回不同的错误消息。

【示例】

<?php
// 首先自定义异常类,继承Exception
class MyException extends Exception {
	public function errorMessage() {
		// 错误消息
		$errorMsg = '异常发生的行:'. $this->getLine() . ' in ' . $this->getFile() . ':<b>' . $this->getMessage(). '</b>不是一个有效的邮箱地址';
		return $errorMsg;
	}
}

// 在实际的业务代码中抛出自定义异常
$email = "someone@yahoo.com";
// 将可能抛出异常的代码放入try中
try {
	// 检查是否符合条件
	if (filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
		// 如果邮件地址无效,则抛出异常
		throw new MyException($email);
	}
	// 检查邮箱是否是雅虎邮箱
	if (strpos($email, "yahoo") !== FALSE) {
		throw new Exception("$email 是一个雅虎邮箱");
	}
} catch (MyException $e) {
	// 显示自定义的消息
	echo $e->errorMessage();
} catch (Exception $e) {
	echo $e->getMessage();
}
?>

程序输出结果:

someone@yahoo.com 是一个雅虎邮箱

设置顶层异常处理器

所有未捕获的异常都可以通过顶层异常处理器来处理。顶层异常处理器使用set_exception_handler()函数实现。

该函数用于创建运行期间用户自己的异常处理方法。该函数会返回旧的异常处理程序,若失败,则返回null。该函数的语法格式如下:

set_exception_handler(callable $exception_handler):callable

设置默认的异常处理程序,用于没有用 try/catch 块来捕获的异常。 在 exception_handler 调用后异常会中止。

参数:

  • exception_handler:当一个未捕获的异常发生时所调用的函数的名称。该处理函数需要接受一个参数,该参数是一个抛出的异常对象。

【示例】

<?php
// 定义顶层的异常处理程序
function myException($exception) {
	echo "<b>异常是:</b>", $exception->getMessage();
}

set_exception_handler('myException');
throw new Exception('正在处理未捕获的异常');  // 抛出异常信息
?>

程序输出结果:

在这里插入图片描述

PHP7中的错误处理

PHP7改变了大多数错误的报告方式。不同于传统(PHP5)的错误报告机制,现在大多数错误都被作为Error异常自动抛出,而不必将错误看作异常抛出。

这种Error异常可以像Exception异常一样被第一个匹配的try/catch块捕获。Error类并非继承自Excepiton类,所以不能用catch(Exception $e)来捕获Error,而是用catch(Error $e)来捕获。

如下代码自动捕获了一个致命错误:

try{
    $a = new cat();
}catch(Error $e){
    echo 'error msg:' . $e->getMessage() .' error line:' . $e->getLine();
}

以上这种形式的错误处理只能在PHP7中可用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值