【PHP学习笔记(八)】错误处理和异常处理

常见的错误和异常

拼写错误

  • 常量和变量都是区分大小写的。函数名、方法名、类名不区分大小写,但建议使用与定义时相同的名字。
  • 预定义常量不区分大小写,但是建议全部大写,包括_LINE_、_FILE_、_DIR_、_FUNCTION_、_CLASS_、_METHOD_、_NAMESPACE_
  • 编写代码输入中文字符后为切换回英文状态,导致输入符号的错误等等

单引号和双引号的混乱

  • 单引号、双引号在PHP中没有特殊的区别,都可以用来创建字符串。双引号串中的内容可以被解释和替换,而单引号串中的内容总被认为是普通字符串

括号使用混乱

  • 括号包含两种语义
    • 分隔符
    • 表达式
  • 避免括号使用层次过多,缺少括号的方法为:先输入完整的括号,再在里面输入内容

等号与赋值混淆

  • 一般出现在if条件判断语句中,在条件判断是否相等时,应该使用“==”运算符

缺少美元符号

  • 在PHP中,设置变量时需要使用美元符号“$”,如果不添加美元符号,就会引起解析错误

调用不存在的常量和变量

  • 如果调用没有声明的常量或者变量,就会触发NOTICE错误

调用不存在的文件

  • 调用不存在文件,程序会直接停止运行并提示错误信息

环境配置的错误

  • 环境配置不当;不同的操作系统采用不同的路径格式;不同的操作系统上的功能也会有差异;这些都有可能导致程序运行错误、

数据库服务器连接错误

  • 由于PHP应用于动态网站的开发,所以经常会对数据库进行基本的操作。在操作系统之前,需要连接数据库服务,如果数据库出现错误,也会导致程序运行出现错误

错误处理

php.ini中的错误处理机制

  • php.ini文件规定了错误的显示方式,包括配置选项的名称、默认值、表述的含义等。
  • 常见的错误配置选项
    • display_errors,默认值:On
      • 设置错误作为PHP的一部分输出。开发过程中可以采用默认的设置,但是为了安全考虑,在生产环境中还是设置为Off比较好
    • error_reporting,默认值:E_all
      • 这个设置会显示所有的出错信息。这种设置会让一些无害的提示也显出出来,所以可以设置默认值为E_all&E_NOTICE,这样只会显示不良编码和错误
    • error_log,默认值:null
      • 设置记录错误日志的文件。在默认情况下将错误发送到Web服务器日志,用户也可以指定写入的文件
    • html_errors,默认值:On
      • 控制是否在错误信息中采用HTML格式
    • log_errors,默认值:Off
      • 控制是否应该将错误发送到主机服务器的日志文件
    • display_startup_errors,默认值:Off
      • 控制是否显示PHP启动时的错误
    • track_errors,默认值:Off
      • 设置是否保存最近一个警告或错误信息

应用DIE语句进行调试

  • 使用DIE语句进行调试的优势是,不仅可以显示错误的位置,还可以输出错误信息,一旦出现错误,程序将会终止运行,并且在浏览器上显示出错之前的信息和错误信息
  • 语法格式:die(“相关的错误信息”)
  • 例如:
if(!file_exits("test.txt")){
die("文件不存在");
}else{
$file=fopen("test.txt","r");
}

自定义错误和错误触发器

  • 创建一个专用函数,在PHP程序发生错误时调用该函数
    • 自定义的错误函数的语法格式-error_function(error_level,error_message,error_file,error_line,error_context)
      • 该函数必须至少包含level和message参数,另外3个参数file、line和context是可选的
      • 各个参数的具体含义
        • error_level:为用户定义的错误规定错误报告级别,必须是一个值
        • error_message:为用户定义的错误规定错误消息
        • error_file:规定错误在其中发生的文件名
        • error_line:规定错误发生的行号
        • error_context:规定一个数组,包含了当错误发生时在使用的每个变量以及它们的值
      • error_level具体的级别值
        • 2:E_WARNING
          • 非致命的run-time错误。不暂停脚本执行
        • 8:E_NOTICE
          • run-time通知。脚本发现可能有错误发生,但也可能在脚本正常运行时发生
        • 256:E_USER_ERROR
          • 致命的用户生成的错误。类似程序员用PHP函数trigger-error()设置的E_ERROR
        • 512:E_USER_WARNING
          • 非致命的用户生成的警告。类似程序员使用PHP函数trigger_error()设置的E_WARNING
        • 1024:E_USER_NOTICE
          • 用户生成的通知。类似程序员用PHP函数trigger-error()设置的E_NOTICE
        • 4096:E_RECOVERABLE_ERROR
          • 可捕获的致命错误。类似于E_ERROR,但可被用户定义的处理程序捕获
        • 8191:E_ALL
          • 所有错误和警告
    • 例如:
function customError($errno,$errstr){
echo "<b>错误:</b> [$errno] $errstr <br />";
echo "终止错误";
die();
}

上述代码是一个简单的错误处理函数。当它被触发时,它会取得错误级别和错误消息。然后它会输出错误级别和消息,并终止程序

  • 创建一个错误处理函数后,下面需要确定在何时触发该函数
    • 使用set_error_handler()函数来设置用户自定义的错误处理函数。该函数用于创建运行期间的用户自己的错误处理方法,该函数会返回旧的错误处理程序,若失败,则返回null
    • 语法格式
      • set_error_handler(error_function,error_types)
      • 其中error_function为必需参数,规定发生错误运行的函数;error_type是可选参数,如果不选择此参数,则表示默认是为”E_ALL”
    • 例如(接上例):
//定义错误函数
function customError($errno,$errstr){
echo "<b>错误:</b> [$errno] $errstr <br />";
}
//设置错误函数的处理
set_error_handler("customError");
//触发自定义错误函数
echo($test);
  • 还可以使用trigger_error()函数创建用户自定义的错误消息
    • 此函数用于在指定的条件下触发一个错误消息。它与内建的错误处理器一同使用,也可以与由ser_error_handler()函数创建的用户自定义函数一起使用。如果指定了一个不合法的错误类型,该函数返回false,否则返回true
    • 语法格式
      • trigger_error(error_message,error_types)
      • error_message为必需参数,规定错误消息,长度限制为1024个字符;error_types为可选参数,规定错误消息的错误类型,可能的值为E_USER_ERROR、E_USER_WARNING或者E_USER_NOTICE
    • 使用trigger_error()函数示例:
$test=5;
if($test>4){
  trigger_error("Value must be 4 or below");
}
  • trigger_error()函数和自定义函数一起使用示例:
//定义错误函数
function customError($errno,$errstr){
  echo "<b>错误:</b> [$errno] $errstr";
}
//设置错误函数的处理
set_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 ( string $message [, int $message_type = 0 [, string $destination [, string $extra_headers ]]] )
    • message为必需参数,表示错误信息;其它均为可选参数;message_type表示错误应该被发送的位置,默认为0;destination表示目标 ,含义由message_type决定;extra_headers为额外的头,具体含义见下
  • message_type可选参数
    • 0:message 发送到 PHP 的系统日志,使用 操作系统的日志机制或者一个文件,取决于 error_log 指令设置了什么
    • 1:message 发送到参数 destination 设置的邮件地址。 第四个参数 extra_headers 只有在这个类型里才会被用到。
    • 2:不再是一个选项。
    • 3: message 被发送到位置为 destination 的文件里。 字符 message 不会默认被当做新的一行。
    • 4: message 直接发送到 SAPI 的日志处理程序中。
  • 以发送到邮箱为例:
function customError($errno,$errstr){
  echo "<b>错误:</b> [$errno] $errstr";
  error_log("错误:[$errno] $errstr <br/>",1,"email_name_receiver@example.com","From:email_name_sender@example.com")
 echo "错误已经发送到邮箱";
}

错误的报告方式(PHP7新变化)

  • PHP7改变了大多数错误的报告方式。不同于PHP5的传统错误报告机制,现在大多数错误被作为Error异常抛出
  • 这种Error异常可以像普通异常一样被try/catch块进行捕获,如果没有匹配的try/catch块,则调用异常处理函数(set_exception_handler())进行处理。如尚未注册异常处理函数,则按照传统方式进行处理——被报告为一个致命错误
  • Error类并不是Exception类扩展出来的,所以用catch(Excecption $e) { ... }这样的代码是捕获不到Error的。用户可以用catch(Error $e) { ... }这样的代码。或者通过注册异常处理函数(set_exception_handler())来捕获Error

例如:

class Mathions
{
  protected $n = 10; 
  //求余数运算,除数为0,抛出异常
  public function dotion() : String
  {
     try{
         $value= $this -> n %0;
         return $value;
     } catch(DivisionByZeroError $e){
         return $e->getMessage();  
      }
  }
$aa= new Mathtions();
print($aa ->dotion());
}

异常处理

异常的基本处理方法

  • 异常处理用于在指定的错误(异常)情况发生时改变脚本的正常执行流程。
  • 当异常发生时,通常会发生以下动作
    • 当前代码状态被保存
    • 代码执行被切换到预定义的异常处理器函数
    • 根据情况,处理器也许会从保存的代码状态重新开始执行代码,终止脚本执行。或从代码中另外的位置继续执行脚本
  • 当异常被抛出时,其后的代码不会被继续执行,PHP会尝试查找匹配的catch代码块。如果异常没有被捕获,而且又没有使用set_exception_handler()做相应的处理的话, 那么将发生一个严重的错误,并且输出Uncaught Exception(未捕获异常)的错误消息
  • 处理异常的程序应当包括以下代码块
    • try代码块
      • 使用异常的函数应该位于try代码块内,如果没有触发异常,则代码将照常继续执行。但是如果异常被触发,会抛出一个异常
    • throw代码块
      • 规定如何触发异常。每一个throw必须对应至少一个catch
    • catch代码块
      • catch代码块会捕获异常,并创建一个包含异常信息的对象
  • 例如:
function checkNum($number){
if($number>1){
throw new Exception("数值必须小于或等于1");
}
return true;
}
try{
checkNum(2);
echo '没有任何异常';
}catch(Exception $e){
echo '异常信息:'.$e->getMessage();
}

自定义的异常处理器

  • 创建一个专门的类,当PHP程序中发生异常时,调用该类的函数即可,该类必须是以Exception类的一个扩展
  • 例如:
class customException extends Exception{
//错误消息 
public function errorMessage(){
  $errorMsg='异常发生的行:'.$this->getLine().' in ' .$this->getFile().'<b>'.$this->getMessage().'</b>不是一个有效的邮箱地址';
return $errorMsg;
}
}
$email="email_name@example.321com";
try{
//检查是否符合条件
if(filter_var($email,FILTER_VALIDATE_EMAIL)===FALSE){
//如果邮件地址无效,则抛出异常
     throw new customException($email);
}
}catch(Exception $e){
//显示自定义的消息
 echo $e->errorMessage();
}

处理多个异常

  • 在上述范例中,只检查了邮箱地址是否有效。如果想检查邮箱是否为雅虎邮箱,或想检查是否有效等多种情况,可以使用if…else代码块,或者一个switch代码块,或者嵌套多个异常

设置顶层异常处理器

  • 所有未捕获的异常都可以通过顶层异常处理器来处理。顶层异常处理器可以使用set_exception_handler()函数来实现。该函数设置自定义的异常处理函数,用于创建运行时期特定的异常处理方式。
  • 语法格式
    • set_exception_handler(exception_function)
    • exception_function为必须的参数,规定未捕获的异常发生时调用的函数,该函数必须在调用set_exception_handler()函数前定义。这个异常处理函数需要一个参数,即抛出的exception对象
  • 例如:
function  myException($exception){
  echo "<b>异常时:</b>", $exception->getMessage();
}
set_exception_handler('myException');
throw new Exception('正在处理未被捕获的异常');

Some Tips

处理异常的原则

  • 需要进行异常处理的代码应该放入try代码块内,以便捕获潜在的异常
  • 每个try和throw代码块必须至少拥有一个对应的catch代码块
  • 使用多个catch代码块可以捕获不同种类的异常
  • 可以在try代码块内的catch代码块中再次抛出(re-throw)异常

如何隐藏错误信息

  • 在调用的函数名前加@符号,这样会隐藏可能由于这个函数导致的错误信息
  • 例如:
@$ab= fopen("123.txt","r");
@fclose();
  • 如果指定的文件不存在,运行程序时就不会出现错误信息了

人已赞赏
PHP编程语言

【PHP学习笔记(七)】面向对象编程

2020-3-29 16:19:16

PHP编程语言

【PHP学习笔记(九)】操作文件与目录

2020-3-31 18:54:24

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
有新私信 私信列表
搜索