【问题标题】:PHP Exception not being caughtPHP 异常没有被捕获
【发布时间】:2016-11-04 04:38:09
【问题描述】:

我正在研究一个通过 PHP 应用程序进行 SVN 更改的类。我正在通过 exec() 调用 svn 命令并尝试在错误时抛出异常以恢复任何更改。

这里是SVN类的相关部分:

private function svn_exec($cmd) {
        $out = array();
        $err = 0;
        exec($cmd, $out, $err);

        if ($err) {
            throw new SVNException("$cmd exited with a status of $err");
        }
    }

还有自定义的 Exception,与 SVN 类包含在同一个文件中:

    class SVNException extends \Exception {
    public function __construct($message = null, $code = 0, \Exception $previous = null) {

        error_log("SVN Error: " . $message);

        parent::__construct("A Subversion error has occurred.", $code, $previous);
    }
}

以及另一个类中的调用代码:

public function ApplySVNChanges() {
    try {
                $svn->update();

                // Do a bunch more stuff...

                $svn->commit();
            } catch (\utils\SVNException $se) { 
                error_log("Exception caught in SVN class."); // <-- Being logged
                $svn->revert();
                throw $se; // Throw to caller so db changes are rolled back
            }
}

SVN 更新抛出了一个 SVNException,然后我才能继续解释为什么我需要弄清楚我的应用程序正在崩溃并且没有像应该那样处理 SVNException。根据错误日志,SVNException 未处理。对 $svn->update() 的调用位于应该捕获 SVNExceptions 的 try/catch 块中,所以我很困惑为什么它没有被处理。

PHP 致命错误:未捕获的异常 'utils\SVNException' 带有消息“发生了颠覆错误。”在 /path/SVNFunctions.php:114\n堆栈跟踪:\n#0 /path/SVNFunctions.php(73): utils\SVNFunctions->svn_exec('svn update --us...')\n#1 /路径/CallingClass.php(120)

更新:在捕获异常时将消息添加到捕获块以记录日志后,我发现正在捕获 SVN 异常,但是当重新抛出它上面调用它的方法时,它没有捕获它。原始的try catch 块是方法的一部分,该方法被另一个具有自己块的方法调用,以恢复 SVN 和 db 更改以保持它们同步。

try {
        ApplySVNChanges(); // Throws SVNException

        // Database related changes...          

        $db-commit();
    } catch (Exception $e) {
        error_log('Caught Exception in main caller.'); // <-- NOT being logged

        if($e instanceof \core\DatabaseException OR $e instanceof \utils\SVNException) {           
            $db->rollback();
        } else {
            throw $e;
        }
    }

根据错误日志,更新命令正在引发异常。它被第一个 catch 捕获,调用了 revert,并且数据库和 SVN 异常的调用方法中的 catch 没有捕获它。

【问题讨论】:

    标签: php exception-handling


    【解决方案1】:

    svn-&gt;revert() 你好吗?会不会是 svn-&gt;revert() 正在调用 svn-&gt;exec 或者在做其他事情导致异常重新抛出?

    我只是在猜测,但如果 revert 可能失败并抛出 SVNException 我认为这就是这里发生的事情..

    您可以通过简单地更改 catch 部分进行测试,例如使用 echo "test"; exit; 而不是 $svn-&gt;revert();

    更新: 更新后,你添加了一个错字,把$throw se改成throw $se

    public function ApplySVNChanges() {
    try {
                $svn->update();
    
                // Do a bunch more stuff...
    
                $svn->commit();
            } catch (\utils\SVNException $se) { 
                error_log("Exception caught in SVN class."); // <-- Being logged
                $svn->revert();
                throw $se; // Throw to caller so db changes are rolled back
            }
    

    }

    【讨论】:

    • 我在 catch 块中添加了消息以确定何时捕获到异常,实际上捕获了 update 中的 SVNException,调用了 revert,并且抛出了 update 中的异常,但未在 try-catch 中捕获它的调用者,问题已更新。
    • revert 可以抛出它自己的异常,但目的是在调用方法中进一步捕获异常。此外,只是为了测试,我将 db->revert 行放在它自己的 try-catch 块中以记录它何时发生并且没有任何东西被抛出。
    • 在你的问题更新中发现了一个错字,所以我也更新了我的答案
    • 已修复,幸好实际程序代码中没有。
    【解决方案2】:

    发现问题。包含对抛出 SVNException 的其他方法的调用的 try-catch 块:

    catch (Exception $e) {
            if($e instanceof \core\DatabaseException OR $e instanceof \utils\SVNException) {           
                $db->rollback();
            } else {
                throw $e;
            }
    }
    

    实际上并没有捕获 SVNExceptions 或 DatabaseExceptions。在 Exception 修复问题之前添加反斜杠:

    catch (\Exception $e) {
    

    SVNExceptions 正在按预期处理。

    编辑:出于好奇,这个对另一个问题的回答:https://stackoverflow.com/a/12170579/5530617 实际上解决了导致 $svn->update() 引发异常的问题,方法是在 shell 命令中添加 --config-dir 选项.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 2013-08-08
      • 2019-08-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多