Какой правильный способ обработки исключений?


20

В ядре Joomla я нахожу еще много таких звонков:

    // Check for errors.
    if (count($errors = $this->get('Errors')))
    {
        JError::raiseError(500, implode("\n", $errors));
        return false;
    }

Но JError устарела с момента выпуска Платформы 12.1. Так как я должен использовать стандартные исключения PHP.


1
Разница заключается в переходе от JError к PHP. Ошибки, к сожалению, не просто в один клик. Поэтому, если вы уверены, что получите исключение, сделайте оператор try / catch, как показано в ответе ниже. Если вы уверены, что получите JError, вам нужно сделать код, аналогичный приведенному выше :)
Джордж Уилсон,

Ответы:


17

Как сказал @DmitryRekun, хорошее обсуждение здесь . Ключевым моментом, который необходимо учитывать во всем этом, является тип ошибки, которая у вас возникает?

Есть два типа ошибок:

  1. Извлекаемые
  2. Неисправимая.

Разницу я склоняюсь к следующему:

Can I still show the page that was requested, even though this error occurred?
  • Да? - Восстанавливаемый
  • Нет? - невосстановимый

Теперь, когда мы знаем, с чем имеем дело. Что вы должны сделать?

Если ошибка не устраняется, вы хотите перенаправить их на страницу ошибки, а не переходить на запрошенную страницу . Это так же просто, как следующее:

throw new Exception(JText::_('COM_MYCOMP_ERROR_MESSAGE_NOT_FOUND'), 404);

Exceptionэто класс, который принимает два параметра, сообщение и код. Рекомендуется использовать коды ответов HTTP, если они соответствуют вашему сценарию.

Если ошибка исправима, вы, скорее всего, просто захотите отобразить сообщение обратно конечному пользователю, продолжая показывать ему запрашиваемую страницу. Обычно это означает, что вы должны «поставить в очередь» сообщение для приложения:

JFactory::getApplication()->enqueueMessage($error, 'error');

enqueueMessageпринимает два параметра: сообщение об ошибке и тип сообщения. Более подробная информация здесь (внизу).


Существует также третья ситуация, которая встречается довольно часто для меня, по крайней мере. Joomla будет генерировать исключения для разных ошибок (например, ошибка запроса к базе данных). Это означает, что Joomla считает эту ошибку невосстановимой. Тем не менее, вы можете продолжить в любом случае. (Например, если я изменяю таблицу при обновлении своего расширения, я могу просто выполнить ALTERзапрос, который выдаст исключение, если таблица была ранее изменена.)

В этом случае вы хотите обернуть код, который может вызвать исключение, в секции try ... catch:

try {
    // exception generating code
    throw new Exception('Normally you would have other code that calls a class that throws the exception', 500);
} catch (Exception $e) {
    $msg = $e->getMessage(); // Returns "Normally you would have other code...
    $code = $e->getCode(); // Returns '500';
    JFactory::getApplication()->enqueueMessage($msg, 'error'); // commonly to still display that error
}

Обратите внимание, что вы «ловите» неисправимую ошибку и заставляете систему восстанавливаться и продолжать показывать запрошенную страницу.


Добавьте все это, и ваш случай должен быть неисправимой ошибкой. (Я знаю это, потому что впоследствии у вас есть «return false», так что вы, вероятно, не планируете продолжать и разочаровываетесь в этой функции.)

Таким образом, я бы переписал это следующим образом:

// Check for errors.
if (count($errors = $this->get('Errors')))
{
    throw new Exception(implode("\n", $errors), 500);
    return false; // you can remove this too, technically since the exception will take you out of this function.
}

Хороший ответ! Но я бы не стал полагаться, $this->get('Errors')потому что это также устарело.
Дмитрий Рекун

Любые комментарии по ошибочным утверждениям, то есть внутренние ошибки? Я бы хотел, чтобы программа сразу же умерла при неудачном утверждении - есть ли способ, специфичный для Joomla? На данный момент я регистрирую обработчик assert, если JDEBUGесть true.
Олле Харстедт

12

Вот как я справляюсь с ошибками.

Просмотр или контроллер

try
{
    $this->item = $this->get('Item');
}
catch (Exception $e)
{
    if ($e->getCode() == 404)
    {
        // Not found
        throw new Exception($e->getMessage(), 404);
    }

    // Generic errors
    JFactory::getApplication()->enqueueMessage(JText::_('COM_MYCOMP_ERROR_OCCURRED'), 'error');
}

Так что, если я получу код 404 от моей модели (например):

if (empty($data))
{
    throw new Exception(JText::_('COM_MYCOMP_ERROR_MESSAGE_NOT_FOUND'), 404);
}

Затем я ловлю его в представлении или контроллере и выкидываю еще одно исключение, которое будет обрабатывать Joomla и отображать страницу 404. Для любого другого я просто показываю пользователю какое-то общее сообщение об ошибке.

Также прочитайте эту интересную дискуссию об обработке ошибок.


4

Большинство таких блоков кода можно просто заменить, enqueueMessageпоскольку они на самом деле не воздействуют на ошибку, а просто используют JErrorдля их распечатки.

// Check for errors.
if (count($errors = $this->get('Errors'))) {
    foreach($errors as $error) {
        JFactory::getApplication()->enqueueMessage($error, 'error');
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.