首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  PHP

PHP 为什么只能用 throw 才能 catch 异常

  •  
  •   gps32251070 · 2016-11-18 15:09:32 +08:00 · 5308 次点击
    这是一个创建于 1060 天前的主题,其中的信息可能已经有所发展或是发生改变。

    之前对抛出的作用的理解是,是逻辑处理层和异常处理层分离。如果不是这样,那么直接用 if...else 语句或者自己写一个不用继承 Exception 的类都可以达到目的了(比如记录日志)。

    但是 php 中异常要 throw 才能 catch ,但是 throw 的时候感觉避免不了 if...else ,这样感觉这个 throw 有点多余啊?还是我的理解有问题 ?

    比如这两种,有什么区别?

    try {
    	if (...) {
        	throw new Exception();
        }
    } catch (Exception $e) {
    	...
    }
    
    if (...) {
    	MyException::log() // 记录或者处理
    }
    

    如果不用 throw 就确实能把逻辑处理层和异常处理分离开

    try {
    	...
    } catch (AException $e) {
    	...
    } catch (BException $e) {
    	...
    } ...
    
    16 回复  |  直到 2016-11-21 10:36:01 +08:00
        1
    sweb   2016-11-18 15:21:30 +08:00
    你理解有问题,我肯定,至少看着我都觉得你混乱。所谓的 throw 就是触发异常,这个 php 没有啥特别之处。
        2
    irgil   2016-11-18 15:26:23 +08:00
    try {
    if (...) {
    throw new Exception();
    }
    } catch (Exception $e) {
    ...
    }
    if (...) {
    MyException::log() // 记录或者处理
    }

    区别在于第一种你不需要立即处理异常。这个 php 没关系...
        3
    gps32251070   2016-11-18 15:26:37 +08:00
    @sweb 哈哈,可能我表达的有些混乱吧,我的意思就是为什么不能自己主动抛出异常,比如在内核层次 throw
        4
    gps32251070   2016-11-18 15:28:30 +08:00
    @irgil 贴这两段代码的意思是为什么不能自动 throw ,这样是有什么好处么?
        5
    wizardoz   2016-11-18 15:39:55 +08:00
    虽然我不懂 PHP 但是异常当然要 throw 才能 catch.
    一些语言看似自动抛出异常,但是我觉得应该理解为特定的异常在标准库中为你 throw 了,比如 IO 接口的异常,因为用户代码接触不到 IO 接口的状态,所以 IO 接口的异常由 IO 标准库 throw.
    但是用户自定义的异常,自然用户自己 throw.

    另外,我认为异常处理不是为了避免 if...else...,而是为了减少多层次的使用 if else.
    假设 d 库调用 c 库,c 库调用 b 库,b 库调用 a 库.如果没有异常处理的话,a 库,b 库,c 库和 d 库都要用 if 判断状态是否正确.但是有了异常处理,可以谁都不用判断状态,只要 a 库 throw 异常,用户代码 catch 异常就可以了.
        6
    irgil   2016-11-18 16:02:26 +08:00
    @wizardoz 运行时异常一般都是自己抛的,楼主显然不了解 throw 是干嘛的。。
        7
    ZiLong   2016-11-18 16:12:15 +08:00
    @gps32251070 以 javaer 观之,是否是受检异常和非受检异常的问题(受检异常被认为是不好的设计,所以 C#抛弃了受检异常的设计
        8
    enenaaa   2016-11-18 16:14:51 +08:00   ♥ 1
    异常机制初衷就是自行触发来转移程序流程, 解决逻辑嵌套太深时错误处理的困难。
    标准库触发的异常只是补充啊。至于 php 的 catch 不捕获系统异常。
    https://secure.php.net/manual/en/language.exceptions.php
    Note:

    Internal PHP functions mainly use Error reporting, only modern Object oriented extensions use exceptions. However, errors can be simply translated to exceptions with ErrorException.

    看起来是历史原因。
        9
    gps32251070   2016-11-18 16:20:41 +08:00
    @enenaaa 所以即能自动抛出系统异常,也能自定义是最好的
        10
    irgil   2016-11-18 16:22:26 +08:00
    @ZiLong 我还以为除了 java 别的语言也是这么干的。。。无知了
        11
    iyaozhen   2016-11-18 16:52:10 +08:00
    @ZiLong 涨姿势了,原来是这种思路的区别。

    自动捕获异常可能比较方便,但容易麻痹大意。我看现在好多 java 代码都是一个 try catch 到底,异常捕获没有细分

    PHP 一般用不上异常捕获,因为 cgi 的运行模型,一次请求挂了就挂了不会影响其它服务。不过开发大的系统还是要做异常处理。现在 php 做常驻进程的也有很多。( php7 的异常捕获能捕获系统异常了)
        12
    jhdxr   2016-11-18 17:55:21 +08:00
    @enenaaa @gps32251070 然而 PHP 7 changes how most errors are reported by PHP. Instead of reporting errors through the traditional error reporting mechanism used by PHP 5, most errors are now reported by throwing Error exceptions. https://secure.php.net/manual/en/language.errors.php7.php
        13
    gps32251070   2016-11-18 17:58:51 +08:00
    @jhdxr 很好,这很 PHP7
        14
    cxbig   2016-11-18 22:08:21 +08:00
    如果有一个异常是你主动抛出来的,当然可以用 if else 结构来简化。

    但是很多情况是:在你的逻辑里只是把参数丢给其他类来处理, Exception 在处理过程中由其他的类抛出来,这时你必须要用 try catch 来抓了
        15
    lianxiaoyi   2016-11-19 17:03:40 +08:00 via Android
    难道 java 不需要先 if?????我收到一个参数 a=1 然后我有一个判断 a 必须大于 3 , java 难道不用判断就知道收到 1 不对然后抛个异常????
        16
    ZiLong   2016-11-21 10:36:01 +08:00
    @irgil 其他语言也是一步步进化过来的,C#也是在 3.0(没记错的话)后去掉的受检异常,还有下面 @jhdxr 说的 PHP7 也是去掉了受检异常,只是 java 进化非常缓慢,有种说法是 C#3.0 约等于 Java 8.0.Java 还是生态好~~Android,大数据,,,,
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3245 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 24ms · UTC 10:32 · PVG 18:32 · LAX 03:32 · JFK 06:32
    ♥ Do have faith in what you're doing.