1.4, 触发错误
在脚本中用户输入数据的位置, 当用户的输入无效时触发错误的很有用的. 在 PHP 中, 这个任务由 trigger_error() 完成.
在本例中, 如果 "test" 变量大于 "1", 就会发生错误:
- <?PHP
- $test=2;
- if ($test>1)
- {
- trigger_error("Value must be 1 or below");
- }
- ?>
以上代码的输出应该类似这样:
- Notice: Value must be 1 or below
- in C:\webfolder\test.PHP on line 6
您可以在脚本中任何位置触发错误, 通过添加的第二个参数, 您能够规定所触发的错误级别.
可能的错误类型:
E_USER_ERROR - 致命的用户生成的 run-time 错误. 错误无法恢复. 脚本执行被中断.
E_USER_WARNING - 非致命的用户生成的 run-time 警告. 脚本执行不被中断.
E_USER_NOTICE - 默认. 用户生成的 run-time 通知. 脚本发现了可能的错误, 也有可能在脚本运行正常时发生.
在本例中, 如果 "test" 变量大于 "1", 则发生 E_USER_WARNING 错误. 如果发生了 E_USER_WARNING, 我们将使用我们的自定义错误处理程序并结束脚本:
- <?PHP
- //error handler function
- function customError($errno, $errstr)
- {
- echo "<b>Error:</b> [$errno] $errstr<br />";
- echo "Ending Script";
- die();
- }
- //set error handler
- set_error_handler("customError",E_USER_WARNING);
- //trigger error
- $test=2;
- if ($test>1)
- {
- trigger_error("Value must be 1 or below",E_USER_WARNING);
- }
- ?>
以上代码的输出应该类似这样:
- Error: [512] Value must be 1 or below
- Ending Script
现在, 我们已经学习了如何创建自己的 error, 以及如何触发它们, 现在我们研究一下错误记录.
1.5 错误记录
默认地, 根据在 PHP.INI 中的 error_log 配置, PHP 向服务器的错误记录系统或文件发送错误记录. 通过使用 error_log() 函数, 您可以向指定的文件或远程目的地发送错误记录.
通过电子邮件向您自己发送错误消息, 是一种获得指定错误的通知的好办法.
通过 E-Mail 发送错误消息
在下面的例子中, 如果特定的错误发生, 我们将发送带有错误消息的电子邮件, 并结束脚本:
- <?PHP
- //error handler function
- function customError($errno, $errstr)
- {
- echo "<b>Error:</b> [$errno] $errstr<br />";
- echo "Webmaster has been notified";
- error_log("Error: [$errno] $errstr",1,
- "someone@example.com","From: webmaster@example.com");
- }
- //set error handler
- set_error_handler("customError",E_USER_WARNING);
- //trigger error
- $test=2;
- if ($test>1)
- {
- trigger_error("Value must be 1 or below",E_USER_WARNING);
- }
- ?>
以上代码的输出应该类似这样:
- Error: [512] Value must be 1 or below
- Webmaster has been notified
接收自以上代码的邮件类似这样:
Error: [512] Value must be 1 or below
这个方法不适合所有的错误. 常规错误应当通过使用默认的 PHP 记录系统在服务器上进行记录.
2, 异常处理
异常 (Exception) 用于在指定的错误发生时改变脚本的正常流程.
什么是异常?
异常处理用于在指定的错误 (异常) 情况发生时改变脚本的正常流程. 这种情况称为异常.
当异常被触发时, 通常会发生:
当前代码状态被保存
代码执行被切换到预定义的异常处理器函数
根据情况, 处理器也许会从保存的代码状态重新开始执行代码, 终止脚本执行, 或从代码中另外的位置继续执行脚本
我们将展示不同的错误处理方法:
异常的基本使用
创建自定义的异常处理器
多个异常
重新抛出异常
设置顶层异常处理器
2.1, 异常的基本使用
当异常被抛出时, 其后的代码不会继续执行, PHP 会尝试查找匹配的 "catch" 代码块.
如果异常没有被捕获, 而且又没用使用 set_exception_handler() 作相应的处理的话, 那么将发生一个严重的错误 (致命错误), 并且输出 "Uncaught Exception" (未捕获异常) 的错误消息.
让我们尝试抛出一个异常, 同时不去捕获它:
- <?PHP
- //create function with an exception
- function checkNum($number)
- {
- if($number>1)
- {
- throw new Exception("Value must be 1 or below");
- }
- return true;
- }
- //trigger exception
- checkNum(2);
- ?>
上面的代码会获得类似这样的一个错误:
- Fatal error: Uncaught exception 'Exception'
- with message 'Value must be 1 or below' in C:\webfolder\test.PHP:6
- Stack trace: #0 C:\webfolder\test.PHP(12):
- checkNum(28) #1 {
- main
- } thrown in C:\webfolder\test.PHP on line 6
Try, throw 和 catch
要避免上面例子出现的错误, 我们需要创建适当的代码来处理异常.
正确的处理程序应当包括:
Try - 使用异常的函数应该位于 "try" 代码块内. 如果没有触发异常, 则代码将照常继续执行. 但是如果异常被触发, 会抛出一个异常.
Throw - 这里规定如何触发异常. 每一个 "throw" 必须对应至少一个 "catch"
Catch - "catch" 代码块会捕获异常, 并创建一个包含异常信息的对象
让我们触发一个异常:
- <?PHP
- // 创建可抛出一个异常的函数
- function checkNum($number)
- {
- if($number>1)
- {
- throw new Exception("Value must be 1 or below");
- }
- return true;
- }
- // 在 "try" 代码块中触发异常
- try
- {
- checkNum(2);
- //If the exception is thrown, this text will not be shown
- echo 'If you see this, the number is 1 or below';
- }
- // 捕获异常
- catch(Exception $e)
- {
- echo 'Message:' .$e->getMessage();
- }
- ?>
上面代码将获得类似这样一个错误:
Message: Value must be 1 or below
例子解释:
上面的代码抛出了一个异常, 并捕获了它:
创建 checkNum() 函数. 它检测数字是否大于 1. 如果是, 则抛出一个异常.
在 "try" 代码块中调用 checkNum() 函数.
checkNum() 函数中的异常被抛出
"catch" 代码块接收到该异常, 并创建一个包含异常信息的对象 ($e).
通过从这个 exception 对象调用 $e->getMessage(), 输出来自该异常的错误消息
不过, 为了遵循 "每个 throw 必须对应一个 catch" 的原则, 可以设置一个顶层的异常处理器来处理漏掉的错误.
2.2, 创建一个自定义的 Exception 类
创建自定义的异常处理程序非常简单. 我们简单地创建了一个专门的类, 当 PHP 中发生异常时, 可调用其函数. 该类必须是 exception 类的一个扩展.
这个自定义的 exception 类继承了 PHP 的 exception 类的所有属性, 您可向其添加自定义的函数.
我们开始创建 exception 类:
- <?PHP
- class customException extends Exception
- {
- public function errorMessage()
- {
- //error message
- $errorMsg = 'Error on line'.$this->getLine().'in'.$this->getFile()
- .': <b>'.$this->getMessage().'</b> is not a valid E-Mail address';
- return $errorMsg;
- }
- }
- $email = "someone@example...com";
- try
- {
- //check if
- if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE)
- {
- //throw exception if email is not valid
- throw new customException($email);
- }
- }
- catch (customException $e)
- {
- //display custom message
- echo $e->errorMessage();
- }
- ?>
这个新的类是旧的 exception 类的副本, 外加 errorMessage() 函数. 正因为它是旧类的副本, 因此它从旧类继承了属性和方法, 我们可以使用 exception 类的方法, 比如 getLine() , getFile() 以及 getMessage().
例子解释:
上面的代码抛出了一个异常, 并通过一个自定义的 exception 类来捕获它:
customException() 类是作为旧的 exception 类的一个扩展来创建的. 这样它就继承了旧类的所有属性和方法.
创建 errorMessage() 函数. 如果 e-mail 地址不合法, 则该函数返回一条错误消息
把 $email 变量设置为不合法的 e-mail 地址字符串
执行 "try" 代码块, 由于 e-mail 地址不合法, 因此抛出一个异常
"catch" 代码块捕获异常, 并显示错误消息
多个异常
可以为一段脚本使用多个异常, 来检测多种情况.
可以使用多个 if..else 代码块, 或一个 switch 代码块, 或者嵌套多个异常. 这些异常能够使用不同的 exception 类, 并返回不同的错误消息:
- <?PHP
- class customException extends Exception
- {
- public function errorMessage()
- {
- //error message
- $errorMsg = 'Error on line'.$this->getLine().'in'.$this->getFile()
- .': <b>'.$this->getMessage().'</b> is not a valid E-Mail address';
- return $errorMsg;
- }
- }
- $email = "someone@example.com";
- try
- {
- //check if
- if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE)
- {
- //throw exception if email is not valid
- throw new customException($email);
- }
- //check for "example" in mail address
- if(strpos($email, "example") !== FALSE)
- {
- throw new Exception("$email is an example e-mail");
- }
- }
- catch (customException $e)
- {
- echo $e->errorMessage();
- }
- catch(Exception $e)
- {
- echo $e->getMessage();
- }
- ?>
例子解释:
上面的代码测试了两种条件, 如何任何条件不成立, 则抛出一个异常:
customException() 类是作为旧的 exception 类的一个扩展来创建的. 这样它就继承了旧类的所有属性和方法.
创建 errorMessage() 函数. 如果 e-mail 地址不合法, 则该函数返回一个错误消息.
执行 "try" 代码块, 在第一个条件下, 不会抛出异常.
由于 e-mail 含有字符串 "example", 第二个条件会触发异常.
"catch" 代码块会捕获异常, 并显示恰当的错误消息
如果没有捕获 customException, 紧紧捕获了 base exception, 则在那里处理异常.
2.3, 重新抛出异常
有时, 当异常被抛出时, 您也许希望以不同于标准的方式对它进行处理. 可以在一个 "catch" 代码块中再次抛出异常.
脚本应该对用户隐藏系统错误. 对程序员来说, 系统错误也许很重要, 但是用户对它们并不感兴趣. 为了让用户更容易使用, 您可以再次抛出带有对用户比较友好的消息的异常:
- <?PHP
- class customException extends Exception
- {
- public function errorMessage()
- {
- //error message
- $errorMsg = $this->getMessage().'is not a valid E-Mail address.';
- return $errorMsg;
- }
- }
- $email = "someone@example.com";
- try
- {
- try
- {
- //check for "example" in mail address
- if(strpos($email, "example") !== FALSE)
- {
- //throw exception if email is not valid
- throw new Exception($email);
- }
- }
- catch(Exception $e)
- {
- //re-throw exception
- throw new customException($email);
- }
- }
- catch (customException $e)
- {
- //display custom message
- echo $e->errorMessage();
- }
- ?>
例子解释:
上面的代码检测在邮件地址中是否含有字符串 "example". 如果有, 则再次抛出异常:
customException() 类是作为旧的 exception 类的一个扩展来创建的. 这样它就继承了旧类的所有属性和方法.
创建 errorMessage() 函数. 如果 e-mail 地址不合法, 则该函数返回一个错误消息.
把 $email 变量设置为一个有效的邮件地址, 但含有字符串 "example".
"try" 代码块包含另一个 "try" 代码块, 这样就可以再次抛出异常.
由于 e-mail 包含字符串 "example", 因此触发异常.
"catch" 捕获到该异常, 并重新抛出 "customException".
捕获到 "customException", 并显示一条错误消息.
如果在其目前的 "try" 代码块中异常没有被捕获, 则它将在更高层级上查找 catch 代码块.
2.4, 设置顶层异常处理器 (Top Level Exception Handler)
set_exception_handler() 函数可设置处理所有未捕获异常的用户定义函数.
- <?PHP
- function myException($exception)
- {
- echo "<b>Exception:</b>" , $exception->getMessage();
- }
- set_exception_handler('myException');
- throw new Exception('Uncaught Exception occurred');
- ?>
以上代码的输出应该类似这样:
Exception: Uncaught Exception occurred
在上面的代码中, 不存在 "catch" 代码块, 而是触发顶层的异常处理程序. 应该使用此函数来捕获所有未被捕获的异常.
异常的规则
需要进行异常处理的代码应该放入 try 代码块内, 以便捕获潜在的异常.
每个 try 或 throw 代码块必须至少拥有一个对应的 catch 代码块.
使用多个 catch 代码块可以捕获不同种类的异常.
可以在 try 代码块内的 catch 代码块中再次抛出 (re-thrown) 异常.
简而言之: 如果抛出了异常, 就必须捕获它.
来源: http://www.bubuko.com/infodetail-2777555.html