ti-enxame.com

Qual é a maneira correta de lidar com exceções?

No núcleo do Joomla, ainda encontro muitas chamadas como esta:

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

Mas o JError está obsoleto desde a liberação da plataforma 12.1. Então, como devo usar o padrão PHP exceções.

20
Harald Leithner

Como @DmitryRekun disse, uma boa discussão é aqui . A peça chave a considerar em tudo isso é que tipo de erro você possui?

Existem dois tipos de erros:

  1. Recuperável
  2. Irrecuperável.

A diferença que tendem a resumir da seguinte forma:

Can I still show the page that was requested, even though this error occurred?
  • Sim? - Recuperável
  • Não? - Irrecuperável

Agora que sabemos com o que estamos lidando. O que você deveria fazer?

Se o erro for irrecuperável, você deseja redirecioná-lo para uma página de erro em vez de continuar na página solicitada . Isso é tão simples quanto o seguinte:

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

Exception é uma classe que aceita dois parâmetros, uma mensagem e um código. Recomenda-se tentar usar o códigos de resposta HTTP se eles se ajustarem ao seu cenário.

Se o erro for recuperável, você provavelmente só deseja exibir uma mensagem para o usuário final enquanto ainda mostra a página solicitada. Isso normalmente significa que você deve 'enfileirar' uma mensagem para o aplicativo:

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

enqueueMessage utiliza dois parâmetros, a mensagem de erro e um tipo de mensagem. Mais informações aqui (na parte inferior).


Há também uma terceira situação que ocorre com bastante frequência para mim, pelo menos. O Joomla lançará exceções para diferentes erros (como um erro de consulta ao banco de dados). Isso significa que o Joomla acha que esse erro é irrecuperável. No entanto, convém continuar assim mesmo. (Por exemplo, se estou alterando uma tabela na atualização da minha extensão, posso executar a consulta ALTER, que emitirá uma exceção se a tabela tiver sido alterada anteriormente.)

Nesse caso, você deseja agrupar o código que pode lançar uma exceção em uma seção 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
}

Observe que o que você está fazendo é "capturar" o erro irrecuperável e forçar o sistema a se recuperar e continuar mostrando a página solicitada.


Adicione tudo isso e seu caso deve ser um erro irrecuperável. (Eu sei disso porque você 'retornou falso' depois, então você provavelmente não planeja continuar e está desistindo da função.)

Assim, eu reescreveria isso da seguinte maneira:

// 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.
}
17
David Fritsch

Aqui está como estou gerenciando um erro.

Visualizar ou Controlador

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

Portanto, se eu receber um código 404 do meu Model (por exemplo):

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

Então eu pego na visualização ou no controlador e ligo mais uma exceção que o Joomla manipulará e exibirá a página 404. Para qualquer outro, apenas mostro uma mensagem de erro genérica para o usuário.

Também leia essa discussão interessante sobre o tratamento de erros.

12
Dmitry Rekun

A maioria dos blocos de código como esse pode simplesmente ser substituída por enqueueMessage, pois na verdade eles não estão agindo sobre o erro e simplesmente usando JError para imprimi-los.

// Check for errors.
if (count($errors = $this->get('Errors'))) {
    foreach($errors as $error) {
        JFactory::getApplication()->enqueueMessage($error, 'error');
    }
}
4
Spunkie