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

20

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 exceções padrão do PHP.

Harald Leithner
fonte
11
A diferença está passando do JError para o PHP Errors, infelizmente não é apenas um processo de um clique. Portanto, se você tiver certeza de que receberá uma exceção, faça uma declaração try / catch como na resposta abaixo. Se você tem certeza que você está indo para obter um JError então você precisa fazer um código semelhante ao acima :)
George Wilson

Respostas:

17

Como o @DmitryRekun disse, uma boa discussão está 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á-los 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. É recomendável tentar usar os 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');

enqueueMessageusa 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 apenas executar a ALTERconsulta, 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.
}
David Fritsch
fonte
Boa resposta! Mas eu não confiaria $this->get('Errors')porque também está obsoleto.
Dmitry Rekun
Algum comentário sobre afirmações com falha, ou seja, erros internos? Eu gostaria que o programa morresse imediatamente com uma afirmação falhada - existe uma maneira específica do Joomla de fazer isso? No momento, registro um manipulador de afirmação, se JDEBUGfor true.
Olle Härstedt 9/10/2015
12

Aqui está como estou gerenciando um erro.

Vista 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 modelo (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.

Leia também esta interessante discussão sobre o tratamento de erros.

Dmitry Rekun
fonte
4

A maioria dos blocos de código como esse pode ser simplesmente substituída por, enqueueMessageuma vez que eles não estão realmente atuando no erro e simplesmente usando-os JErrorpara imprimi-los.

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