【问题标题】:Does re-throwing an exception in PHP destroy the stack trace?在 PHP 中重新抛出异常会破坏堆栈跟踪吗?
【发布时间】:2016-04-27 16:36:32
【问题描述】:

在 C# 中,执行以下操作会破坏异常的堆栈跟踪:

try{
    throw new RuntimeException();
}
catch(Exception e){
    //Log error

    //Re-throw
    throw e;
}

因此,首选使用throw 而不是throw e。这将使相同的异常向上传播,而不是将其包装在一个新异常中。

但是,在 PHP 中使用 throw; 而不指定异常对象是无效的语法。这个问题在PHP中根本不存在吗?如下使用 throw $e 不会破坏堆栈跟踪吗?

<?php

try{
    throw new RuntimeException();
}
catch(Exception $e){
    //Log error

    //Re-throw
    throw $e;
}

【问题讨论】:

    标签: php exception-handling


    【解决方案1】:

    当您像以前一样在 PHP 中抛出 $e 时,您重新抛出现有异常对象而不更改其任何内容并发送所有给定信息,包括捕获的异常的堆栈跟踪 - 所以您的第二个示例是重新抛出异常的正确方法在 PHP 中。

    如果(无论出于何种原因)您想在最后一条消息中抛出新位置,则必须重新抛出一个新创建的异常对象:

    throw new RuntimeException( $e->getMessage() );
    

    请注意,这不仅会丢失堆栈跟踪,还会丢失除消息之外的异常对象中可能包含的所有其他信息(例如,CodeFileLine for RuntimeException)。所以这一般不推荐

    【讨论】:

    • 为什么你会抛出一个新的异常,来自旧异常的消息,而不是再次抛出旧异常?这种方法背后的逻辑是什么?在这种情况下,您应该使用异常链。
    【解决方案2】:

    重新抛出相同的异常不会破坏堆栈跟踪。 但是根据您的需要,您可能只想抛出相同的异常或构建异常链(请参阅 PHP 文档 > Exception::__construct

    this answer 很好地解释了人们何时以及为何选择一种方法而不是另一种方法

    【讨论】:

      【解决方案3】:

      是的。这是捕获异常并重新抛出带有堆栈跟踪数据的相同异常对象的最佳方法。一旦到达处理请求的方法点,只需将其捕获并相应地将响应发送回用户。

      抛出一个新的异常对象会丢失堆栈跟踪并创建一个导致内存负载的附加对象是个坏主意。

      希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 2011-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-02
        • 1970-01-01
        • 1970-01-01
        • 2023-03-19
        • 2011-05-12
        相关资源
        最近更新 更多