PHP 异常处理

PHP 异常处理


异常用于在指定的错误发生时改变脚本的正常流程。


异常是什么

PHP 5 提供了一种新的面向对象的错误处理方法。

异常处理用于在指定的错误(异常)情况发生时改变脚本的正常流程。这种情况称为异常。

当异常被触发时,通常会发生:

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

我们将展示不同的错误处理方法:

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

注释:异常应该仅仅在错误情况下使用,而不应该用于在一个指定的点跳转到代码的另一个位置。


异常的基本使用

当异常被抛出时,其后的代码不会继续执行,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:webfoldertest.php:6
Stack trace: #0 C:webfoldertest.php(12):
checkNum(28) #1 {main} thrown in C:webfoldertest.php on line 6

Try、throw 和 catch

要避免上面实例中出现的错误,我们需要创建适当的代码来处理异常。

适当的处理异常代码应该包括:

  1. Try - 使用异常的函数应该位于 "try" 代码块内。如果没有触发异常,则代码将照常继续执行。但是如果异常被触发,会抛出一个异常。
  2. Throw - 里规定如何触发异常。每一个 "throw" 必须对应至少一个 "catch"。
  3. Catch - "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. 在 "try" 代码块中调用 checkNum() 函数。
  3. checkNum() 函数中的异常被抛出。
  4. "catch" 代码块接收到该异常,并创建一个包含异常信息的对象 ($e)。
  5. 通过从这个 exception 对象调用 $e->getMessage(),输出来自该异常的错误消息。

然而,为了遵循 "每个 throw 必须对应一个 catch" 的原则,可以设置一个顶层的异常处理器来处理漏掉的错误。


创建一个自定义的 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 类来捕获它:

  1. customException() 类是作为旧的 exception 类的一个扩展来创建的。这样它就继承了旧的 exception 类的所有属性和方法。
  2. 创建 errorMessage() 函数。如果 e-mail 地址不合法,则该函数返回一条错误消息。
  3. 把 $email 变量设置为不合法的 e-mail 地址字符串。
  4. 执行 "try" 代码块,由于 e-mail 地址不合法,因此抛出一个异常。
  5. "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();
}
?>

实例解释:

上面的代码测试了两种条件,如果其中任何一个条件不成立,则抛出一个异常:

  1. customException() 类是作为旧的 exception 类的一个扩展来创建的。这样它就继承了旧的 exception 类的所有属性和方法。
  2. 创建 errorMessage() 函数。如果 e-mail 地址不合法,则该函数返回一个错误消息。
  3. 把 $email 变量设置为一个字符串,该字符串是一个有效的 e-mail 地址,但包含字符串 "example"。
  4. 执行 "try" 代码块,在第一个条件下,不会抛出异常。
  5. 由于 e-mail 含有字符串 "example",第二个条件会触发异常。
  6. "catch" 代码块会捕获异常,并显示恰当的错误消息。

如果 customException 类抛出了异常,但没有捕获 customException,仅仅捕获了 base exception,则在那里处理异常。


重新抛出异常

有时,当异常被抛出时,您也许希望以不同于标准的方式对它进行处理。可以在一个 "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"。如果有,则再次抛出异常:

  1. customException() 类是作为旧的 exception 类的一个扩展来创建的。这样它就继承了旧的 exception 类的所有属性和方法。
  2. 创建 errorMessage() 函数。如果 e-mail 地址不合法,则该函数返回一个错误消息。
  3. 把 $email 变量设置为一个字符串,该字符串是一个有效的 e-mail 地址,但包含字符串 "example"。
  4. "try" 代码块包含另一个 "try" 代码块,这样就可以再次抛出异常。
  5. 由于 e-mail 包含字符串 "example",因此触发异常。
  6. "catch" 代码块捕获到该异常,并重新抛出 "customException"。
  7. 捕获到 "customException",并显示一条错误消息。

如果在当前的 "try" 代码块中异常没有被捕获,则它将在更高层级上查找 catch 代码块。


设置顶层异常处理器

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 代码块中抛出(再次抛出)异常。

简而言之:如果抛出了异常,就必须捕获它。

转载于:https://www.cnblogs.com/navysummer/p/8393417.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/354162.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使用Elixir和Phoenix快速入门构建CRUD REST API

这篇文章将展示如何使用Elixir和Phoenix框架构建REST API。 重点将是为持久化到Postgres数据库后端的模型提供CRUD&#xff08;创建&#xff0c;读取&#xff0c;更新&#xff0c;删除&#xff09;端点。 我应该警告你&#xff1b; 这是一个简单的例子。 但是&#xff0c;希望它…

01背包(修订版)

由于时间比较充裕&#xff0c;重新修订一部分。 这次把一些补充的放进来&#xff0c;其他的基础说明见后半部分 这些一共说明&#xff1a;01背包、完全背包、多重背包 将会详细说明。 三种背包混合、二维背包、分组背包、依赖背包、泛化背包 将大致说明。 01背包 如上次说明一…

java 马踏棋盘优化_我所知道的十大常用算法之马踏棋盘算法(深度搜索、贪心思想优化 )...

前言需求今天我们学习的是马踏棋盘算法&#xff0c;我们还是从一个场景里引入看看马踏棋盘算法也被称为骑士周游问题将马随机放在国际象棋的66棋盘Board0&#xff5e;5的某个方格中提示&#xff1a;马按走棋规则(马走日字)进行移动要求&#xff1a;每个方格只进入一次&#xff…

app engine_App Engine中的Google Services身份验证,第2部分

app engine在本教程的第一部分中&#xff0c; 我介绍了如何使用OAuth进行Google API服务的访问/身份验证。 不幸的是&#xff0c;正如我稍后发现的那样&#xff0c;我使用的方法是OAuth 1.0&#xff0c;显然现在Google正式弃用了OAuth 1.0&#xff0c;改用OAuth 2.0版本。 显然…

Django知识总结(一)

壹 ● 有关http协议 一 ● 全称 超文本传输协议(HyperText Transfer Protocol) 二 ● 协议 双方遵循的规范 http协议是属于应用层的协议(还有ftp, smtp等), 即浏览器请求消息和服务器响应消息的一系列规则 三 ● http协议的特性 http是无状态、无连接的协议(stateless, connect…

java数组使用实验报告_JAVA数组与类的定义-java实验报告

JAVA数组与类的定义-java实验报告JAVA数组与类的定义-java实验报告、实验目的与要求1、 熟悉Java类、对象和方法的一般操作练习等。2、 熟悉数组等的定义和使用。二、实验内容及步骤(包括源程序和运行结果截图)1. 编写Java小应用程序&#xff0c;程序中自定义一个方法&#xff…

JPA 2.1和Java EE 7中的JPQL增强功能(第1部分– JOIN ON)

Java EE 7已经存在了几年&#xff0c;它提供了一些非常有用且期待已久的功能&#xff0c;例如实体图以及对存储过程和结果映射的更好支持。 有关概述&#xff0c;请参阅Thorben Janssen的博客文章 。 但是&#xff0c;我想添加有关JPA查询语言功能的更详细的摘要。 在JPQL和Cri…

mysql+if+x+mod+2_Windows 下 MantisBT 2.X + Apache 2.4 + PHP 7 + MySQL 5.7 的环境配置

Apache 2.4.25~ Visual C Redistributable for Visual Studio 2015PHP 7.1.3~ mod_fcgid-2.3.9Mantisbt-2.2.1MySQL Database 5.7.17~ NET Framework 3.5安装 Apache前期准备1.若计算机已安装了 Apache2.4 以前的版本&#xff0c;请自行卸载并删除安装目录。2.以管理员身份运行…

ASP.NET MVC ActionMethodSelectorAttribute 以及HttpGet等Action特性

一、ActionMethodSelectorAttribute 其是一个抽象类&#xff0c;继承自Attribute&#xff0c;子类有NonActionAttribute、HttpGetAttribute、HttpPostAttribute、HttpPutAttribute、HttpDeleteAttribute、HttpPatchAttribute、HttpHeadAttribute、HttpOptionsAttribute和Accept…

java 中map_Java中Map集合

1. Java中Map集合1. Map中value可以重复&#xff0c;key不能重复。对于重复的key值来说&#xff0c;后放置的值对覆盖前放置的值。import java.util.HashMap;public class MapTest1{public static void main(String[] args){HashMap map new HashMap();map.put("a",…

如何在Java中对文件进行模式匹配和显示相邻行

最近&#xff0c;我们在jOOλ0.9.9中发布了有关超棒的窗口函数支持的文章 &#xff0c;我相信这是对我们所做的库的最佳补充。 今天&#xff0c;我们将在一个用例中研究窗口函数的出色应用&#xff0c;该用例受到以下堆栈溢出问题Sean Nguyen的启发&#xff1a; 如何从Java 8…

64位内核第二讲,进程保护之对象钩子

64位内核第二讲,进程保护. 一丶什么是保护. 什么是保护. 比如我们安装了xxx杀毒软件.那么此时你用任务管理器关闭.是关闭不了的.原因是内核已经做了保护. 那么去掉保护的前提就是你要给自己的软件做保护. 比如我们给计算器做保护. 例如下图. 做保护.以前的病毒作者.都是想要退出…

java 类 request_java普通类得到request对象

使用拦截器import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.…

Xamarin.Forms Button长按事件

Xamarin.Forms Button长按事件 在平时的开发中&#xff0c;我们经常遇到需要Button能够拥有长按事件&#xff0c;但是在Xamarin.Forms中Button并没有该事件&#xff0c; 此时我们如何来实现呢&#xff1f; 我们知道在Xamarin.Forms中可以通过CustomRenderer来根据不同平台各自处…

java对象写入文件_将Java对象写入文件中

Java对象序列化 首先介绍一下对象序列化的目标:对象序列化的目标是将对象保存到磁盘中,或允许在网络中直接传输对象。 一、序列化的含义和意义: 序列化机制使得对象可以脱离程序的运行而独立存在。 对象的序列化指将一个Java对象写入IO流中,与此对应的反是,对象的反序列化…

jpql hql_无需部署即可测试JPQL / HQL

jpql hql您是否曾经想在不完全部署应用程序的情况下测试JPQL / HQL&#xff1f; 我们今天在这里看到的是适用于任何JPA实现的简单解决方案&#xff1a;Hibernate&#xff0c;OpenJPA&#xff0c;EclipseLink等。 这篇文章中找到的基本源代码来自本书&#xff1a;“ Pro JPA 2&a…

eclipse 代码上传github 笔记

第一步 先share project 如图所示 第二步 如果所示 第三步 点击 下面的create 然后点击完成 第四步提交 第五步&#xff1a; 第六步&#xff1a; 转载于:https://www.cnblogs.com/a8457013/p/8410471.html

java private 对象_[Java笔记]类的所有构造器都是private权限,就一定没有办法实例化它的对象了么?...

笔者以前学过C语言。众所周知&#xff0c;C也是一门面向对象程序设计语言。还记得当时在大学的时候&#xff0c;老师讲过这样的话&#xff1a;类的构造函数不应该设置成private权限&#xff0c;这样的话还怎么去实例化类的对象&#xff1f;当时也信以为然。现在在学java&#x…

[Usaco2008 Feb]Eating Together麻烦的聚餐

Description 为了避免餐厅过分拥挤&#xff0c;FJ要求奶牛们分3批就餐。每天晚饭前&#xff0c;奶牛们都会在餐厅前排队入内&#xff0c;按FJ的设想所有第3批就餐的奶牛排在队尾&#xff0c;队伍的前端由设定为第1批就餐的奶牛占据&#xff0c;中间的位置就归第2批就餐的奶牛了…

Keycloak SSO集成到jBPM和Drools Workbench中

介绍 单一登录&#xff08;SSO&#xff09;和相关令牌交换机制正在成为Web上不同环境中进行身份验证和授权的最常见方案&#xff0c;尤其是在迁移到云中时。 本文讨论了Keycloak与jBPM或Drools应用程序的集成&#xff0c;以便使用Keycloak上提供的所有功能。 Keycloak是用于浏…