例外确实是您的最佳选择,它们会满足您的要求。甚至多条消息也是可能的,因为异常只是您可以扩展的类。您可以将导致异常的对象传递给所述异常。
<?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 方法将消息存储在会话中,以便在刷新后显示它们(只是不要忘记清除会话中的消息,否则它们将一遍又一遍地显示;-)。