最新的Web开发教程
 

PHP异常处理


例外用于如果发生指定的错误改变脚本的正常流动。


什么是异常

随着PHP 5来处理错误的一个新的面向对象的方式。

异常处理用于如果指定的错误改变代码执行的正常流动(exceptional)条件发生。 这种情况被称为异常。

这是当异常被触发,通常会发生什么:

  • 当前代码状态被保存
  • 该代码执行将切换到预定义的(custom)异常处理函数
  • 根据不同的情况,处理程序就可以恢复的代码保存状态下执行,中止执行脚本或从其他位置继续脚本代码

我们会表现出不同的错误处理方法:

  • 基本使用的例外
  • 创建自定义异常处理程序
  • 多个异常
  • 重新抛出异常
  • 设置顶层异常处理程序

Note:例外只应该错误的条件下使用,而不应使用在指定点跳转到另一地点的代码。


例外的基本使用

当一个异常被抛出,下面的代码就不会被执行,而PHP将试图找到匹配的"catch"块。

如果一个异常没有被捕获,一个致命的错误将与发出"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

尝试,抛出和捕获

为了避免从上面例子中的错误,我们需要创建适当的代码来处理异常。

适当的异常代码应包括:

  1. 使用异常应在一个功能-尝试"try"块。 如果异常不会触发,代码将继续正常。 但是,如果触发的例外,一个异常"thrown"
  2. 扔掉 - 这是你如何触发一个例外。 每一个"throw"必须至少有一个"catch"
  3. 捉-甲"catch"块检索一个例外,并创建包含异常信息的对象

让我们尝试触发有效代码的异常:

<?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 in a "try" block
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
catch(Exception $e) {
  echo 'Message: ' .$e->getMessage();
}
?>

上面的代码会获得类似这样的错误:

Message: Value must be 1 or below

为例进行了说明:

上面的代码抛出异常和捕获它:

  1. 所述checkNum()创建功能。 它检查,如果数大于1,如果是,则抛出异常
  2. checkNum()函数被调用一个"try"
  3. 该范围内的异常checkNum()函数抛出
  4. "catch"块检索异常,并创建一个对象($e)包含异常信息
  5. 从异常的错误消息是由呼叫呼应$e-> getMessage()从所述异常对象

然而,一个办法让周围的"every throw must have a catch"规则是设定一个最高水平异常处理程序来处理漏网之鱼错误。


创建一个自定义异常类

要创建您必须创建一个特殊类时异常在PHP时,可以调用函数的自定义异常处理程序。 类必须是异常类的扩展。

自定义异常类从PHP的异常类继承的属性,你可以添加自定义的功能吧。

让我们创建一个异常类:

<?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 = "[email protected]";

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();
}
?>

新的类是旧的例外类与另外的一个副本errorMessage()函数。 既然是老类的副本,并将其从旧的类继承的属性和方法,我们可以使用异常类的方法,如getLine()getFile()getMessage()

为例进行了说明:

上面的代码抛出异常,并用一个定制的异常类捕获它:

  1. customException()类为旧的例外类的扩展创建。 这样,它继承了旧的例外类的所有方法和属性
  2. 所述errorMessage()创建功能。 如果电子邮件地址无效,该函数返回一个错误信息
  3. 在$电子邮件变量设置为一个字符串,这不是一个有效的电子邮件地址
  4. "try"块被执行并抛出一个异常,因为电子邮件地址无效
  5. "catch"块捕捉异常并显示错误消息

多个异常

这是可能的脚本中使用多个异常检查多个条件。

有可能使用几种的if..else块,一个开关,或嵌套多个异常。 这些例外可以使用不同的异常类返回不同的错误信息:

<?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 = "[email protected]";

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();
}
?>

为例进行了说明:

上面的代码测试两个条件,并且如果任一条件不满足抛出异常:

  1. customException()类为旧的例外类的扩展创建。 这样,它继承了旧的例外类的所有方法和属性
  2. 所述errorMessage()创建功能。 如果电子邮件地址无效,该函数返回一个错误信息
  3. 在$电子邮件变量设置为一个字符串,是一个有效的电子邮件地址,但包含字符串"example"
  4. "try"块被执行,一个异常没有抛出的第一个条件
  5. 由于电子邮件包含字符串的第二个条件触发的异常"example"
  6. "catch"块捕捉异常并显示正确的错误消息

如果抛出的异常是类customException并没有customException抓,只有基本异常捕获,异常将在那里处理。


重新抛出异常

有时,当抛出一个异常,你可能希望以不同的方式处理它比标准的方式。 它可以抛出一个异常内的第二次"catch"块。

脚本应该对用户隐藏系统错误。 系统错误可能是编码器很重要,但不感兴趣的用户。 为了让事情变得更容易为用户,您可以重新引发与用户友好的消息的异常:

<?php
class customException extends Exception {
  public function errorMessage() {
    //error message
    $errorMsg = $this->getMessage().' is not a valid E-Mail address.';
    return $errorMsg;
  }
}

$email = "[email protected]";

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"在里面,如果这样做,异常被重新抛出:

  1. customException()类为旧的例外类的扩展创建。 这样,它继承了旧的例外类的所有方法和属性
  2. 所述errorMessage()创建功能。 如果电子邮件地址无效,该函数返回一个错误信息
  3. 在$电子邮件变量设置为一个字符串,是一个有效的电子邮件地址,但包含字符串"example"
  4. "try"块包含另一个"try"块,使之可能重新抛出异常
  5. 被触发的异常,因为电子邮件包含字符串"example"
  6. "catch"块捕获该异常,并重新抛出一个"customException"
  7. 所述"customException"被捕获并显示错误消息

如果该异常不能在其目前陷入"try"块,它将搜索在catch块"higher levels"


设置顶层异常处理

所述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可以用来捕获不同的类的例外
  • 异常可以被抛出(or re-thrown)在catch块try块内

一个简单的规则:如果你扔东西,你必须抓住它。