因此,我捕捉到一个异常(Exception类的实例),我想要做的是更改它的异常消息。如何更改异常对象的异常消息?
我能得到这样的异常消息:
$e->getMessage();
但是如何设置一个例外消息?这将不起作用:
$e->setMessage('hello');
因此,我捕捉到一个异常(Exception类的实例),我想要做的是更改它的异常消息。如何更改异常对象的异常消息?
我能得到这样的异常消息:
$e->getMessage();
但是如何设置一个例外消息?这将不起作用:
$e->setMessage('hello');
您无法更改异常消息。
然而,你可以确定它是类名和代码,并抛出一个新的,同一类,相同的代码,但有不同的消息。
是的,你可以看到我的答案:http://stackoverflow.com/a/20441768/582917 – CMCDragonkai
当然,异常消息可以被覆盖。这个答案不应该被接受。 – Fahmi
您无法更改由Exception类给出的消息。如果您想要自定义消息,则需要使用$ e-> getCode()检查错误代码并创建自己的消息。
你可以用自己的扩展异常,并投入了先导作用,它
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;
}
}
由于某些原因,不幸的是getMessage()在PHP中被声明为final,并且上面的代码不起作用。 – romaninsh
如果你真的想这样做(中唯一的情况下,我能想到的,你可能想这样做),你可以重新抛出异常:
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();
}
像这样重新抛出的问题是你失去堆栈跟踪 –
您可以扩展异常并使用parent :: __构造来设置您的消息。这解决了您无法重写getMessage()的问题。
class MyException extends Exception {
function __construct() {
parent::__construct("something failed or malfunctioned.");
}
}
这不能解决OP的问题。他们想要更改现有异常的消息,而不是使用硬编码消息创建新消息。 –
您无法更改异常消息。选举委员会通过接受这样的答复来承认这一点。 –
只要做到这一点,它的工作原理我测试了它。
<?php
class Error extends Exception{
public function setMessage($message){
$this->message = $message;
}
}
$error = new Error('blah');
$error->setMessage('changed');
throw $error;
+1。为了避免混淆,我会将其命名为“Error”以外的其他名称,但我假设这仅仅是为了举例。 –
PHP中没有本地错误类,所以可以创建自己的错误处理设置。 – CMCDragonkai
错误总是一个保留字,并且现在有一个[Error Class](http://php.net/manual/en/class.error.php)(后者是@ CMCDragonkai制作时不存在的东西他们在2014年的评论,尽管前者依然如此)。 – DanielM
这里是我正在使用的一个generified片段。
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());
}
对于几乎在阳光下的每一个案件,您应该抛出一个新的例外与旧的例外附加。
try {
dodgyCode();
}
catch(\Exception $oldException) {
throw new MyException('My extra information', 0, $oldException);
}
Every在一段时间一次虽然,你真正需要处理到位的例外,因为抛出另一个异常是不是你真正想做的事。
一个很好的例子是BehatFeatureContext
当你想附加@AfterStep
方法的附加信息。在一个步骤失败后,您可能希望截取屏幕截图,然后向输出添加一条消息,以了解可以看到截图的位置。
因此,为了改变异常的消息,在那里你可以取代它,你不能把一个新的异常,你可以使用反射来暴力破解的参数值:
$message = " - My appended message";
$reflectionObject = new \ReflectionObject($exception);
$reflectionObjectProp = $reflectionObject->getProperty('message');
$reflectionObjectProp->setAccessible(true);
$reflectionObjectProp->setValue($exception, $exception->getMessage() . $message);
这里的那个例子在上下文中的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
}
}
}
同样,如果你可以避免它,你永远不应该这样做。
来源:My old boss
一个丑陋的黑客攻击,如果你不知道你在处理哪种异常(即可以拥有自己的属性)是使用反射。
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;
}
你应该在非常特殊的情况下明智地使用这个垃圾,当你没有任何其他选择。
更改异常消息(几乎总是)没有意义。你为什么想这样做? – Corbin
@Corbin嗯,我正在维护一个旧的遗留系统。我需要在不改变大量代码的情况下解决某个bug,因为这需要大量的没有时间的新测试。基本上改变一个异常信息是修复这个错误的最麻烦和侵入性的方法(非常丑陋,但功能性最重要)。 –
对于那些已回答抛出新异常的应用程序,您将丢失具有原始异常的堆栈跟踪。因此,如果代码中出现异常(从库代码中抛出),则可能需要处理原始异常,以便其他层可以正确解释它,同时保持堆栈跟踪完好无损。 –