php - How to change exception message of Exception object?

533

So I catch an exception (instance of Exception class) and what I want to do is change its exception message.

I can get the exception message like this:

$e->getMessage();

But how to set an exception message? This won't work:

$e->setMessage('hello');
256

Answer

Solution:

For almost every single case under the sun, you should throw a new Exception with the old Exception attached.

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

Every once in a while though, you do actually need to manipulate an Exception in place, because throwing another Exception isn't actually what you want to do.

A good example of this is in BehatFeatureContext when you want to append additional information in an@AfterStep method. After a step has failed, you may wish to take a screenshot, and then add a message to the output as to where that screenshot can be seen.

So in order to change the message of an Exception where you can just replace it, and you can't throw a new Exception, you can use reflection to brute force the parameters value:

$message = " - My appended message";

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

Here's that example the Behat in context:

    /**
     * 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
            }
        }
    }

Again, you should never do this if you can avoid it.

Source: My old boss

576

Answer

Solution:

Just do this, it works I tested it.

<?php

class Exception2 extends Exception{

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

$error = new Exception2('blah');

$error->setMessage('changed');

throw $error;
964

Answer

Solution:

You can't change Exception message.

You can however determine it's class name and code, and throw a new one, of the same class, with same code, but with different message.

586

Answer

Solution:

You can extend Exception and use the parent::__construct to set your message. This gets around the fact that you cannot override getMessage().

class MyException extends Exception {
    function __construct() {
        parent::__construct("something failed or malfunctioned.");
    }
}
932

Answer

Solution:

here a generified snippet i'm using.

    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());
    }
478

Answer

Solution:

An ugly hack if you don't know which kind of exception you're handling (that can have its own properties) is to use reflection.

    try {
        // business code
    } catch (\Exception $exception) {
        $reflectedObject = new \ReflectionClass(get_class($exception));
        $property = $reflectedObject->getProperty('message');
        $property->setAccessible(true);
        $property->setValue($exception, "new message");
        $property->setAccessible(false);
        throw $exception;
    }

You should use this crap wisely in very specific case when you don't have any other choice.

10

Answer

Solution:

You can't change the message given by the Exception class. If you wanted a custom message, you would need to check the error code using $e->getCode() and create your own message.

239

Answer

Solution:

If you really wanted to do this (in the only situation I can think that you might want to do it), you could re-throw the exception:

function throwException() {
    throw new Exception( 'Original' );
}

function rethrowException() {
    try {
        throwException();
    } catch( Exception $e ) {
        throw new Exception( 'Rethrow - ' . $e->getMessage() );
    }
}

try {
    rethrowException();
} catch( Exception $e ) {
    echo $e->getMessage();
}
497

Answer

Solution:

You can extend Exception with your own, and put a setter in it

class MyException extends Exception
{
  private $myMessage = '';
  public function getMessage()
  {
    if ($this->myMessage === '') {
    return parent::getMessage();
  } else {
    return $this->myMessage;
  }

  public function setMessage($msg)
  {
    $this->myMessage = $msg;
  }
}
61

Answer

Solution:

The php Exception class has a__toString() method which is the only method within the Exception class that is notfinal, meaning it can be customised.

class HelloMessage extends Exception {
    function __toString() {
        return $this->getMessage()." you have an error with code: ".$this->getCode();
    }
}

You use it as follows withintry-catch block:

try {
    if (2 > 0) {
        throw new HelloMessage("Hello", 10);
    }
} catch (HelloMessage $e) {
    echo $e;
}

Output would be:

Hello you have an error with code: 10

People are also looking for solutions to the problem: session - why would session_set_save_handler not be working PHP 5.2

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.