организация технических и пользовательских сообщений об ошибках в php - PullRequest
4 голосов
/ 11 января 2010

У меня небольшие проблемы с организацией сообщений об ошибках для двух взаимодействующих классов. У одного объекта есть состояния, которые являются «ошибочными», когда что-то пошло не так или произошло неожиданно, но ситуация все еще может быть исправлена. Я не хочу использовать исключения, 1. потому что они имеют только одну строку для сообщения, и 2. потому что я хочу получить доступ к объекту после ошибки. По крайней мере, я хочу использовать некоторые из его методов get () для создания полезного сообщения об ошибке после исключения!

В конечном итоге у меня есть два сообщения, которые я хочу передать: одно для меня как кодера, что-то пошло не так. Эта строка будет содержать технические данные файла, строки, функции / метода, аргументов и результатов. Очевидно, я не хочу показывать это пользователю, поэтому есть еще одна строка сообщения об ошибке, которую я хочу показать пользователю (вид «Этот адрес электронной почты не был найден»).

Поэтому мне приходит мысль создать массив сообщений об ошибках, который может использовать код ошибки из исключений или код состояния в качестве ключей для различных сообщений. (Хотя, если я сделаю это, где я буду хранить массив сообщений?) Другой вариант может заключаться в создании объекта состояния ошибки.

Есть ли что-то вроде "шаблонов ошибок", похожих на шаблоны проектирования?

Ответы [ 2 ]

7 голосов
/ 13 января 2010

Исключения действительно ваш лучший вариант, они делают все, что вы просили. Возможно даже несколько сообщений, поскольку исключения - это просто классы, которые вы можете расширять. Вы можете просто передать объект, который вызывает исключение, в указанное исключение.

<?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 );
}

Расширение Exception имеет то преимущество, что вы также получаете возврат стека. Обратный след содержит информацию о том, в каком файле, строке и функции произошло исключение. Вы также можете получить код ошибки, сообщение и многое другое. Я предлагаю вам прочитать документацию PHP об исключениях (http://php.net/manual/en/class.exception.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 хранить сообщения в сеансе, чтобы они могли отображаться после обновления (просто не забудьте удалить сообщения из сеанса, иначе они будут отображаться снова и снова; -).

0 голосов
/ 11 января 2010

Я не хочу использовать исключения, 1. потому что они имеют только одну строку для сообщения и 2. потому что я хочу получить доступ к объекту после ошибки. По крайней мере, я хочу использовать некоторые его методы get () для создания полезное сообщение об ошибке после исключение!

Вы можете создавать свои собственные классы исключений и расширять классы исключений PHP, добавляя необходимую поддержку. Однако, возможно, у вас может быть две настройки: разработчик и клиент, где ошибки клиента выводятся на экран, а ошибки разработчика не переходят в файл журнала или что-то подобное.

Что, переводится на два пользовательских типа исключений (хотя вы могли бы иметь гораздо больше, я говорю два разных базовых класса).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...