¿Cuál es la forma correcta para el manejo de excepciones?

20

En el núcleo de Joomla todavía encuentro muchas llamadas como esta:

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

Pero JError está en desuso desde la versión de plataforma 12.1. Entonces, ¿cómo debo usar las excepciones PHP estándar?

Harald Leithner
fuente
1
La diferencia es que pasar de JError a PHP Errores no es simplemente un proceso de un solo clic, lamentablemente. Entonces, si está seguro de que obtendrá una excepción, haga una declaración try / catch como en la respuesta a continuación. Si está seguro de que va a obtener un JError, entonces necesita hacer un código similar al anterior :)
George Wilson

Respuestas:

17

Como @DmitryRekun dijo, una buena discusión está aquí . La pieza clave a considerar en todo esto es ¿qué tipo de error tiene?

Hay dos tipos de errores:

  1. Recuperable
  2. Irrecuperable.

La diferencia tiendo a resumir de la siguiente manera:

Can I still show the page that was requested, even though this error occurred?
  • ¿Sí? - recuperable
  • ¿No? - Irrecuperable

Ahora que sabemos a qué nos enfrentamos. Que deberias hacer

Si el error es irrecuperable, desea redirigirlos a una página de error en lugar de continuar a la página solicitada . Eso es tan simple como lo siguiente:

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

Exceptiones una clase que toma dos parámetros, un mensaje y un código. Se recomienda intentar usar los códigos de respuesta HTTP si se ajustan a su escenario.

Si el error es recuperable, es probable que solo desee mostrar un mensaje al usuario final sin dejar de mostrarle la página que solicitó. Esto generalmente significa que debe 'poner en cola' un mensaje para la aplicación:

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

enqueueMessagetoma dos parámetros, el mensaje de error y un tipo de mensaje. Más información aquí (en la parte inferior).


También hay una tercera situación que ocurre con bastante frecuencia al menos para mí. Joomla lanzará excepciones para diferentes errores (como un error de consulta de la base de datos). Esto significa que Joomla piensa que este error es irrecuperable. Sin embargo, es posible que desee continuar de todos modos. (Por ejemplo, si estoy alterando una tabla en la actualización de mi extensión, simplemente puedo ejecutar la ALTERconsulta, lo que arrojará una excepción si la tabla se ha modificado previamente).

En ese caso, desea ajustar el código que podría generar una excepción en una sección 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
}

Tenga en cuenta que lo que está haciendo es "detectar" el error irrecuperable y obligar al sistema a recuperarse y continuar mostrando la página solicitada.


Agregue todo esto y su caso debería ser un error irrecuperable. (Lo sé porque después tienes 'return false', por lo que es probable que no planees continuar y renuncies a la función).

Por lo tanto, volvería a escribir esto de la siguiente manera:

// 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
fuente
¡Buena respuesta! Pero no confiaría en $this->get('Errors')ello porque también está en desuso.
Dmitry Rekun
¿Algún comentario sobre afirmaciones fallidas, es decir, errores internos? Me gustaría que el programa muriera inmediatamente ante una afirmación fallida: ¿hay alguna forma específica de Joomla para hacer esto? Por el momento, registro un controlador de aserción si JDEBUGes true.
Olle Härstedt
12

Así es como estoy gestionando un error.

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

Entonces, si obtengo un código 404 de mi Modelo (por ejemplo):

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

Luego lo capto en la vista o controlador y lanzo una Excepción más que Joomla manejará y mostrará la página 404. Para cualquier otro, solo muestro un mensaje de error genérico al usuario.

Lea también esta interesante discusión sobre el manejo de errores.

Dmitry Rekun
fuente
4

La mayoría de los bloques de código como este simplemente se pueden reemplazar, enqueueMessageya que en realidad no están actuando sobre el error y simplemente se usan JErrorpara imprimirlos.

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