如何更改Exception对象的异常消息?

Ric*_*nop 19 php

所以我捕获一个异常(Exception类的实例),我想要做的是更改它的异常消息.

我可以得到这样的异常消息:

$e->getMessage();
Run Code Online (Sandbox Code Playgroud)

但是如何设置异常消息?这不起作用:

$e->setMessage('hello');
Run Code Online (Sandbox Code Playgroud)

Dan*_*elM 24

对于几乎所有在阳光下的情况,你应该抛出一个新的Exception并附加旧的Exception.

try {
    dodgyCode();
}
catch(\Exception $oldException) {
    throw new MyException('My extra information', 0, $oldException);
}
Run Code Online (Sandbox Code Playgroud)

但是,每隔一段时间,你确实需要操作异常,因为抛出另一个异常并不是你想要做的事情.

当您想要在方法中附加其他信息时,Behat 就是一个很好的例子.步骤失败后,您可能希望截取屏幕截图,然后在输出中添加一条消息,以查看屏幕截图的位置.FeatureContext@AfterStep

因此,为了更改Exception的消息,您可以只替换它,并且不能抛出新的Exception,您可以使用反射来强制参数值:

$message = " - My appended message";

$reflectionObject = new \ReflectionObject($exception);
$reflectionObjectProp = $reflectionObject->getProperty('message');
$reflectionObjectProp->setAccessible(true);
$reflectionObjectProp->setValue($exception, $exception->getMessage() . $message);
Run Code Online (Sandbox Code Playgroud)

这是Behat在上下文中的示例:

    /**
     * Save screen shot on failure
     * @AfterStep
     * @param AfterStepScope $scope
     */
    public function saveScreenShot(AfterStepScope $scope) {
        if (!$scope->getTestResult()->isPassed()) {
            try {
                $screenshot = $this->getSession()->getScreenshot();
                if($screenshot) {
                    $filename = $this->makeFilenameSafe(
                        date('YmdHis')."_{$scope->getStep()->getText()}"
                    );
                    $filename = "{$filename}.png";
                    $this->saveReport(
                        $filename,
                        $screenshot
                    );
                    $result = $scope->getTestResult();
                    if($result instanceof ExceptionResult && $result->hasException()) {
                        $exception = $result->getException();

                        $message = "\nScreenshot saved to {$this->getReportLocation($filename)}";

                        $reflectionObject = new \ReflectionObject($exception);
                        $reflectionObjectProp = $reflectionObject->getProperty('message');
                        $reflectionObjectProp->setAccessible(true);
                        $reflectionObjectProp->setValue($exception, $exception->getMessage() . $message);
                    }
                }
            }
            catch(UnsupportedDriverActionException $e) {
                // Overly specific catch
                // Do nothing
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

同样,如果你能避免它,你永远不应该这样做.

来源:我的老板

  • 这应该是可以接受的答案,这是更加有用和期望的 (2认同)

CMC*_*kai 20

只是这样做,它测试它的工作原理.

<?php

class Error extends Exception{

    public function setMessage($message){
        $this->message = $message;
    }

}

$error = new Error('blah');

$error->setMessage('changed');

throw $error;
Run Code Online (Sandbox Code Playgroud)

  • 错误始终是一个保留字,现在有一个[错误类](http://php.net/manual/en/class.error.php)(后者是@CMCDragonkai制作他们的时候不存在的东西在2014年评论,虽然前者仍然是真的). (7认同)
  • +1。为了避免混淆,我将其命名为“ Error”以外的其他名称,但是我假设这只是出于示例的目的。 (2认同)

Nam*_*ess 8

您无法更改异常消息.

但是,您可以确定它的类名和代码,并使用相同的代码但使用不同的消息抛出同一类的新类.

  • 你可以,看看我的回答:http://stackoverflow.com/a/20441768/582917 (3认同)
  • 当然可以覆盖异常消息.不应接受这个答案. (2认同)

Dav*_*han 6

这是我正在使用的通用片段。

    foreach ($loop as $key => $value) 
    {
        // foo($value);
        thow new Special_Exception('error found')
    }
    catch (Exception $e)
    {
        $exception_type = get_class($e);
        throw new $exception_type("error in $key :: " . $e->getMessage());
    }
Run Code Online (Sandbox Code Playgroud)


Jay*_*enu 5

您可以扩展Exception并使用parent :: __ construct设置您的消息。这可以避免无法覆盖getMessage()的事实。

class MyException extends Exception {
    function __construct() {
        parent::__construct("something failed or malfunctioned.");
    }
}
Run Code Online (Sandbox Code Playgroud)