我在组织两个交互类的错误消息时遇到了一些麻烦。一个对象的状态是'error-ish',出现问题,或意外发生,但情况仍然可以挽救。我不想使用异常,1。因为它们只有一个字符串用于消息,而且2.因为我想在错误之后访问该对象。至少,我想使用它的一些get()方法在异常后构造一个有用的错误消息!
最终我有两条想要传达的信息:一个是我自己作为编码员,有些事情出了问题。该字符串将包含文件,行,函数/方法,参数和结果的技术详细信息。显然,我不想向用户显示这个,所以我想向用户显示另一个错误消息字符串(“找不到那个电子邮件地址”的东西)。
因此我想到了构建一个错误消息数组,它可以使用异常的错误代码或状态代码作为各种消息的键。 (虽然如果我这样做,我在哪里存储消息数组?)另一个选择可能是创建一个错误状态对象。
是否有类似“错误模式”的内容,类似于设计模式?
答案 0 :(得分:7)
例外确实是你最好的选择,他们会做你要求的一切。甚至可能有多条消息,因为异常只是您可以扩展的类。您可以将导致异常的对象传递给所述异常。
<?php
class ExampleException extends Exception {
private $secondMessage;
private $objectThatCausedIt;
public function __construct( $secondMessage, $objectThatCausedIt ) {
parent::__construct(
"Descriptive message for developer",
// error code for this type of error
1000 );
$this->secondMessage = $secondMessage;
$this->objectThatCausedIt = $objectThatCausedIt;
}
public function getSecondMessage() {
return $this->secondMessage;
}
public function getObjectThatCausedIt() {
return $this->objectThatCausedIt;
}
}
class Example {
public function causeException() {
throw new ExampleException( "Second Message", $this );
}
}
现在你只需使用该类并将可能引发异常的调用包装在try-catch块中。
<?php
$example = new Example();
try {
$example->causeException();
}
catch ( ExampleException $e ) {
// kind of pointless here, just an illustration
// get object that caused it and do something with it.
dump_and_log_function( $e->getObjectThatCausedIt() );
// or just use $example, which is still "alive"
// and references the same instance
dump_and_log_function( $example );
}
扩展异常的好处是您还可以获得堆栈回溯。回溯包含发生异常的文件,行和函数等信息。您还可以访问错误代码,消息等。我建议您阅读有关例外(http://php.net/manual/en/class.exception.php)的PHP文档以获取更多信息。
关于错误消息和日志记录,我通常使用单例类。单例类只有一个自身实例(如果你不知道的话。)这是一个非常简单的例子:
<?php
class Log {
private $logFile;
private static $instance;
/* Log instances may only be constructed in Log::getInstance */
private function __construct() {
$this->logFile = fopen( "path/to/log/file", "a" );
}
public logMessage( $message ) {
fwrite( $this->logFile, $message );
}
public static getInstance() {
if ( !self::$instance ) self::$instance = new self();
return self::$instance;
}
}
现在回到异常处理throw-catch块,您可以将其更改为:
<?php
$example = new Example();
try {
$example->causeException();
}
catch ( ExampleException $e ) {
// log developer message and backtrace
Log::getInstance()->logMessage( $e->getMessage() );
Log::getInstance()->logMessage( $e->getTraceAsString() );
// or more compact by casting to string
Log::getInstance()->logMessage( (string)$e );
// and now print error for users
echo "<p>An Error has occured: {$e->getSecondMessage()}</p>";
}
您可以使Log类具有包含消息数组的属性,而不是立即回显错误消息。然后,您可以稍后在视图脚本中列出它们。您还可以使logMessage方法将消息存储在会话中,以便在刷新后显示它们(只是不要忘记清除会话中的消息,否则它们会一遍又一遍地显示; - )。
答案 1 :(得分:0)
我不想使用例外,1。 因为他们只有一个字符串 对于消息,和2.因为我想要 在错误之后访问该对象。 至少,我想用一些 它的get()方法构造一个 之后有用的错误信息 例外!
您可以创建自己的异常类,并可以扩展PHP的异常类,添加所需的支持。但是,您可能有两个设置,开发人员和客户端,其中客户端错误转到显示,而开发人员错误则不会转到日志文件或其他内容。
其中,转换为两种自定义异常类型(尽管你可以有更多,我说的是两个不同的基类)。