PHP中的异常及其处理机制

目录
  • 什么是异常?
  • 总结

上回文章中我们讲到了错误是编译和语法运行时会出现的,它们与逻辑无关,是程序员在码代码时不应该出现的,也就是说,这些错误应该是尽量避免带到线上环境的,他们不能通过try...catch捕获到。而异常则正好相反。

什么是异常?

异常,指的是程序运行中出现的不符合预期的情况,通常允许它发生,并交由相应的异常处理来进行处理。当然,你也可以选择忽略掉异常的处理,但是就像严重错误一样,代码马上会终止运行。异常属于业务逻辑上的错误,基本上是我们人为的。

还是先通过一个简单的代码看下异常的抛出和捕获:

function test()
{
    throw new Exception('This is test Error...');
}

try {
    test();
} catch (Exception $e) {
    print_r($e);
}

我们通过 throw 来抛出异常,然后在调用方法时将方法包裹在 try...catch 块中来捕获抛出的异常。这就是异常最基础的结构。

从这里我们可以看出,异常基本都是通过我们手动进行抛出的,让外部来进行处理。在PHP内部多数也是在类中会进行异常的抛出,这就是面向对象的错误处理思想了。比如说PDO类:

try {
    // $pdo = new PDO(); // Fatal error: Uncaught ArgumentCountError: PDO::__construct() expects at least 1 parameter, 0 given
    $pdo = new PDO('');
} catch (PDOException $e) {
    print_r($e); // invalid data source name
}

注意上面那行注释的代码,没有传参数是错误,是无法捕获的。而传了的参数不对,就是异常了,在PDO类的源码中发现参数不对进行了抛出。交给上层代码也就是我们这些调用方来进行捕获。

接下来,我们看下自定义的异常类和finally语句块的使用。

自定义的异常类都会去继承 Exception 类,这个类可以看做是所有异常的基类。它的结构如下:

class Exception
{
    protected $message = 'Unknown exception';   // 异常信息
    private   $string;                          // __toString cache
    protected $code = 0;                        // 用户自定义异常代码
    protected $file;                            // 发生异常的文件名
    protected $line;                            // 发生异常的代码行号
    private   $trace;                           // backtrace
    private   $previous;                        // previous exception if nested exception

    public function __construct($message = null, $code = 0, Exception $previous = null);

    final private function __clone();           // 不能被复制,如果clone异常类将直接产生致命错误

    final public  function getMessage();        // 返回异常信息
    final public  function getCode();           // 返回异常代码
    final public  function getFile();           // 返回发生异常的文件名
    final public  function getLine();           // 返回发生异常的代码行号
    final public  function getTrace();          // backtrace() 数组
    final public  function getPrevious();       // 之前的 exception
    final public  function getTraceAsString();  // 已格成化成字符串的 getTrace() 信息

    // Overrideable
    public function __toString();               // 可输出的字符串
}

注意上面那行注释的代码,没有传参数是错误,是无法捕获的。而传了的参数不对,就是异常了,在PDO类的源码中发现参数不对进行了抛出。交给上层代码也就是我们这些调用方来进行捕获。

接下来,我们看下自定义的异常类和finally语句块的使用。

自定义的异常类都会去继承 Exception 类,这个类可以看做是所有异常的基类。它的结构如下:

class Exception
{
    protected $message = 'Unknown exception';   // 异常信息
    private   $string;                          // __toString cache
    protected $code = 0;                        // 用户自定义异常代码
    protected $file;                            // 发生异常的文件名
    protected $line;                            // 发生异常的代码行号
    private   $trace;                           // backtrace
    private   $previous;                        // previous exception if nested exception

    public function __construct($message = null, $code = 0, Exception $previous = null);

    final private function __clone();           // 不能被复制,如果clone异常类将直接产生致命错误

    final public  function getMessage();        // 返回异常信息
    final public  function getCode();           // 返回异常代码
    final public  function getFile();           // 返回发生异常的文件名
    final public  function getLine();           // 返回发生异常的代码行号
    final public  function getTrace();          // backtrace() 数组
    final public  function getPrevious();       // 之前的 exception
    final public  function getTraceAsString();  // 已格成化成字符串的 getTrace() 信息

    // Overrideable
    public function __toString();               // 可输出的字符串
}

通过上述类定义,我们可以看出,我们能重写 构造函数 和 __toString() 方法,也能使用一些受保护的属性。那么我们就来定义一个自定义的异常类吧。

class TestException extends Exception
{
    protected $code = 200;

    public function __construct($message = null, $code = 0, Exception $previous = null){
        $this->message = 'TestException:' . $message;
    }

    public function __toString(){
        return 'code: ' . $this->code . '; ' . $this->message;
    }
}

function test2()
{
    throw new TestException('This is test2 Error...');
}

try {
    test2();
} catch (TestException $e) {
    echo $e, PHP_EOL; // code: 200; TestException:This is test2 Error...
}

还是非常好理解的吧,大部分的PHP框架都会有自定义异常的组件或者能力供我们使用,因为现代框架还是以面向对象为基础的,所以异常会定义的比较详细。不同组件会提供不同的异常类来进行异常的提示封装。

接下来就是 finally 关键字,其实这个并没有什么可多说的,finally 的特点就是不管有没有出现异常,都会去执行 finally 关键字所定义代码块内部的内容。

try {
    test2();
} catch (TestException $e) {
    echo $e, PHP_EOL;
} finally {
    echo 'continue this code ...', PHP_EOL;
}
// code: 200; TestException:This is test2 Error...
// continue this code ...

说了这么多,最后我们来结合上述内容来处理下除0错误的异常抛出。在文章开头已经说过,错误是应该避免的,而异常是属于逻辑业务的。所以当我们接到一个需要做除法的参数时,可以先判断这个数是否为0,如果是0的话,就抛出异常让上层调用者来处理,如果不是0的话,就让它正常进行除法运算就好了。

function test3($d)
{
    if ($d == 0) {
        throw new Exception('除数不能为0');
    }
    return 1 / $d;
}

try {
    echo test3(2), PHP_EOL;
} catch (Exception $e) {
    echo 'Excepition:' . $e->getMessage(), PHP_EOL;
} finally {
    echo 'finally:继续执行!', PHP_EOL;
}

// 0.5
// finally:继续执行!

try {
    echo test3(0), PHP_EOL;
} catch (Exception $e) {
    echo 'Excepition:' . $e->getMessage(), PHP_EOL;
} finally {
    echo 'finally:继续执行!', PHP_EOL;
}

// Excepition:除数不能为0
// finally:继续执行!

总结

异常相关的使用就是这些了,通过这两篇文章,相信大家已经对PHP的错误和异常有了一些直观的了解了。接下来的文章我们将一起对比下错误和异常,并且说明一下PHP7对错误有了哪些改进。内容依然精彩,值得期待哦!!

以上就是PHP中的异常及其处理机制的详细内容,更多关于PHP 异常的资料请关注我们其它相关文章!

(0)

相关推荐

  • Thinkphp5框架异常处理操作实例分析

    本文实例讲述了Thinkphp5框架异常处理操作.分享给大家供大家参考,具体如下: 异常处理 有时候服务端会报出我们无法感知的错误,TP5默认会自动渲染错误的形式,生产环境中这样的形式并不是我们想要的. 未知错误 1.exception\Handle.php下的render方法需要覆盖 创建ApiHandleException.php <?php namespace app\common\lib\exception; use think\exception\Handle; class ApiHa

  • PHP使用观察者模式处理异常信息的方法详解

    本文实例讲述了PHP使用观察者模式处理异常信息的方法.分享给大家供大家参考,具体如下: 异常信息的捕获对编程测试有着重要的意义,这里结合观察者模式,探索如何处理异常信息. 关于观察者模式,如果还没有接触过的话,博客园有很多优秀的博友做了详细的 解释.笔者觉得,所谓观察者模式,必须有两个重要组成部分:一个主题对象,多个观察者.在使用的时候,我们可以将观察者像插头一样插到主题对象这个插座上,利用主题对象完成相应功能. 既然观察者要作为插头,必须要有一个统一的口径才能插到相同的插座上,因而先定义一个接

  • php异常处理捕获错误整理

    PHP的错误报告有三种: 1.错误,语法解析错误,致命错误 2.警告 3.注意 后果: 错误 -> 致命错误,会终止已下程序的执行,语法错误的话,PHP压根就没执行. 警告 -> 他不会终止运行,但会影响结果. 注意 -> 不会终止执行,也不会影响结果. 为了让用户得到更好的体验,我们屏蔽所有错误的输出,是输出,而不是显示.但这样的话,管理员也看不到错误了.页面上不显示错 误,而将错误生成一个日志,提供给管理员查看. error_reporting(~E_ALL)将所有输出都屏蔽掉了,自

  • Laravel 解决composer相关操作提示php相关异常的问题

    Laravel 的一大特色就是使用 composer 来管理依赖包,这使得整个项目的升级.扩展变得异常容易.一般情况下,只需要我们输入几个命令并按下回车,就能完成插件包的安装.更新以及卸载工作. 但有时候你会碰到一种比较有意思的问题.那就是使用 composer 进行相关安装.更新插件操作的时候,却报 PHP 程序异常.比如,github中一个项目,在你上次更新之后上游代码又加入新功能,使用了一个新的依赖包.这时你使用git pull更新代码后,依赖包并没有安装,那么再用composer upd

  • PHP中的异常处理机制深入讲解

    1.异常概述 异常(Exception)是一种错误处理机制,用于在指定的错误发生时改变脚本的正常流程. 当异常被触发时,当前代码状态被保存,代码执行被切换到预定义的异常处理器函数(如果有) 根据情况,处理器也许会从保存的代码状态重新开始执行代码,终止脚本执行,或从代码中另外的位置继续执行脚本 2.异常的基本使用 当异常被抛出时,其后的代码不会继续执行,PHP 会尝试查找匹配的 "catch" 代码块. 如果异常没有被捕获,而且又没用使用 set_exception_handler()

  • 让whoops帮我们告别ThinkPHP6的异常页面

    春节期间熟悉了TP6, 也写了一个TP6的博客程序,但系统的异常页面实在另外头疼,很多时候无法查看到是哪行代码出的问题. 所以就特别的想把whoops引进来,经过一系列的研究,终于找到了解决的办法: 1. 通过composer安装whoops 运行命令:  composer require filp/whoops 注意:composer引进的文件如果有语法错误,需要提前把语法错误处理好才能进行安装,否则一直报错. 2. 使用whoops接管tp6的异常处理 在/app/ExceptionHand

  • PHP批斗大会之缺失的异常详解

    故事的开始 这几天观察错误日志发现有一个数据反序列化的notice错误,实际情况我是从缓存中读取数据然后反序列化,因为反序列化失败,所以实际每次都是去数据库取的值.背后性能影响还是挺大的. 缺失的异常 刚开始写代码的时候一直不明白为什么要用异常,感觉if else就能搞定了,为什么还要多此一举,现在反而觉得 php 的异常太少. 对比两种序列化场景,一个是json,另一个是serialize. json 在json encode/decode的时候,如果出现异常,可以通过json_last_er

  • 再谈PHP错误与异常处理

    目录 一.异常与错误的概述 PHP中什么是异常 PHP中什么是错误 上面的说法是有前提条件的 PHP异常处理很鸡肋? 二.ERROR的级别 三.PHP异常处理中的黑科技 1:set_error_handler() 2:register_shutdown_function() 3:set_exception_handler() 四.巧妙的捕获错误和异常 1:把错误以异常的形式抛出(不能完全抛出) 2:捕获所有的错误 五.自定义异常处理和异常嵌套 1:自定义异常处理 2:异常嵌套 六.PHP7中的异

  • Thinkphp 在api开发中异常返回依然是html的解决方式

    现在谁不开发接口的呢?但是在接口开发过程中,报错误异常后居然返回错误的信息依然是html信息!TP官方也不知道为啥不添加,说好的为接口而生,我的解决方案也很简单,把系统的异常处理类复制出来,去掉模板相关,直接以json方式输出 下面是解决方案: 1:按照TP扩展异常的方式引用这个文件 https://www.kancloud.cn/manual/thinkphp5_1/354092 // 判断默认输出类型 // $app 是配置数组 if ($app['default_return_type']

  • Java中的异常和处理机制实例详解

    本文实例讲述了Java中的异常和处理机制.分享给大家供大家参考,具体如下: 简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?或者用C语言风格:用函数返回值作为执行状态?. Java提供了更加优秀的解决办法:异常处理机制. 异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰. Java中的异常可以是函数中的

  • PHP中的异常及其处理机制

    目录 什么是异常? 总结 上回文章中我们讲到了错误是编译和语法运行时会出现的,它们与逻辑无关,是程序员在码代码时不应该出现的,也就是说,这些错误应该是尽量避免带到线上环境的,他们不能通过try...catch捕获到.而异常则正好相反. 什么是异常? 异常,指的是程序运行中出现的不符合预期的情况,通常允许它发生,并交由相应的异常处理来进行处理.当然,你也可以选择忽略掉异常的处理,但是就像严重错误一样,代码马上会终止运行.异常属于业务逻辑上的错误,基本上是我们人为的. 还是先通过一个简单的代码看下异

  • 解析PHP中Exception异常机制

    异常的基本使用 当异常被抛出时,其后的代码不会继续执行,PHP 会尝试查找匹配的 "catch" 代码块. 如果异常没有被捕获,而且又没用使用 set_exception_handler() 作相应的处理的话,那么将发生一个严重的错误(致命错误),并且输出 "Uncaught Exception" (未捕获异常)的错误消息. 让我们尝试抛出一个异常,同时不去捕获它: <?php //create function with an exception funct

  • 深入探讨JAVA中的异常与错误处理

    异常与错误: 异常: 在Java中程序的错误主要是语法错误和语义错误,一个程序在编译和运行时出现的错误我们统一称之为异常,它是VM(虚拟机)通知你的一种方式,通过这种方式,VM让你知道,你(开发人员)已经犯了个错误,现在有一个机会来修改它.Java中使用异常类来表示异常,不同的异常类代表了不同的异常.但是在Java中所有的异常都有一个基类,叫做Exception. 错误: 它指的是一个合理的应用程序不能截获的严重的问题.大多数都是反常的情况.错误是VM的一个故障(虽然它可以是任何系统级的服务).

  • 剖析Java中的事件处理与异常处理机制

    一.事件处理 其实,由事件处理这个名字自然就想到MFC中的消息响应机制,就我的体会,它们应该算是南桔北枳的情形吧,我怀疑Java中的事件处理这个"新瓶"应是装的MFC中的消息响应这个"旧酒".     所谓的"事件"即如键盘按键.鼠标点击等这类由动作或什么导致某个状态改变并需要对这个改变作相应响应的这类改变.我们可以将Java中的事件分为按钮.鼠标.键盘.窗口.其它事件这几大类.     事件处理模型  1.   基于继承的事件处理模型(JDK1

  • python中的五种异常处理机制介绍

    从几年前开始学习编程直到现在,一直对程序中的异常处理怀有恐惧和排斥心理.之所以这样,是因为不了解.这次攻python,首先把自己最畏惧和最不熟悉的几块内容列出来,里面就有「异常处理」这一项. <Dive into Python>并没有专门介绍异常处理,只是例子中用到的时候略微说明了一下.今天下载<Learn Python>,直接进异常处理这块.这一部分有四章,第一章讲解异常处理的一般使用方法,后面的章节深入地讨论其机制.我目前只看了第一章,先学会用,以后有必要的时候再扩展阅读. p

  • .NET中的异常和异常处理用法分析

    本文较为详细的分析了.NET中的异常和异常处理用法.分享给大家供大家参考.具体分析如下: .NET中的异常(Exception) .net中的中异常的父类是Exception,大多数异常一般继承自Exception. 可以通过编写一个继承自Exception的类的方式,自定义异常类! 异常处理机制: 复制代码 代码如下: Try {     //可能发生异常的代码     //后续代码     } //Try以外的代码 catch(Exception e) { } finally { } 上述代

  • Android开发中优秀的app 异常处理机制

    一个好的app 异常处理机制 我认为应该至少包含以下几个功能: 1.能把错误信息上传到服务器  让开发者可以持续改进app 2.错误信息至少应该包含 是否在主进程 是否在主线程 等可以帮助程序员定位的信息 3.最好包含手机硬件及软件信息. 4.主进程引发的异常 最好交由系统自己处理 也就是让用户可以感知到 那种(当然你也可以自己定义一套更有意思的感知系统对话框等,具体可参考各种有意思的404界面) 5.子进程引发的异常最好别让用户感知到.比如push之类的 这种 和用户感知弱关联的这种.最好发生

  • php中的异常和错误浅析

    本文主要介绍了php中的异常和错误,分享给大家供大家参考学习,下面来一起看看详细的介绍: 一.异常与错误 异常是指程序运行中不符合预期情况以及与正常流程不同的状况.错误则属于自身问题,是一种非法语法或者环境问题导致的.让编译器无法通过检查设置无法运行的情况. 由于php最开始是没有异常处理,后来为了进军企业级开发,模仿java等语言,推出了异常.导致php中遇到任何自身错误都会触发一个错误,而不是抛出一个异常(某些情况下,会同时抛出错误和异常).PHP一旦遇到非正常代码,大多数情况下,都是直接抛

  • 解析Java的迭代器中的fast-fail错误检测机制

    fail-fast 机制是java集合(Collection)中的一种错误机制.当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件.例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了:那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件. fail-fast 机制是java集合(Collection)中的一种错误机制.当多个线程对同一个集合的内容进行操作时,

随机推荐