web-dev-qa-db-fra.com

Quelle est la bonne façon de gérer les exceptions?

Dans Joomla core, je trouve encore de nombreux appels comme celui-ci:

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

Mais JError est déconseillé depuis la version 12.1 de la plate-forme. Alors, comment utiliser les exceptions standard PHP.

20
Harald Leithner

Comme @DmitryRekun l'a dit, une bonne discussion est ici . L'élément clé à prendre en compte dans tout cela est le type d'erreur que vous avez?

Il y a deux types d'erreurs:

  1. Restaurable
  2. Irrécupérable.

La différence que j'ai tendance à résumer comme suit:

Can I still show the page that was requested, even though this error occurred?
  • Oui? - Restaurable
  • Non? - irrécupérable

Maintenant que nous savons ce que nous traitons. Que devrais tu faire?

Si l'erreur est irrécupérable, vous souhaitez les rediriger vers une page d'erreur au lieu de passer à la page demandée . C'est aussi simple que ce qui suit:

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

Exception est une classe qui prend deux paramètres, un message et un code. Il est recommandé d'essayer d'utiliser le Codes de réponse HTTP s'ils correspondent à votre scénario.

Si l'erreur est récupérable, vous souhaiterez probablement simplement afficher un message à l'utilisateur final tout en leur montrant la page qu'ils ont demandée. Cela signifie généralement que vous devez "mettre en file d'attente" un message pour l'application:

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

enqueueMessage prend deux paramètres, le message d'erreur et un type de message. Plus d'infos ici (en bas).


Il y a aussi une troisième situation qui se produit assez souvent au moins pour moi. Joomla lancera des exceptions pour différentes erreurs (telles qu'une erreur de requête de base de données). Cela signifie que Joomla pense que cette erreur est irrécupérable. Cependant, vous voudrez peut-être continuer quand même. (Par exemple, si je modifie une table lors de la mise à jour de mon extension, je peux simplement exécuter la requête ALTER, qui lève une exception si la table a déjà été modifiée.)

Dans ce cas, vous souhaitez encapsuler le code susceptible de générer une exception dans une section 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
}

Notez que vous "rattrapez" l'erreur irrécupérable et vous obligez le système à récupérer et à continuer d'afficher la page demandée.


Ajoutez tout cela et votre cas devrait être une erreur irrécupérable. (Je le sais parce que vous avez "rendu faux" après, alors vous ne prévoyez probablement pas de continuer et vous abandonnez la fonction.)

Ainsi, je réécrirais ceci comme suit:

// 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

Voici comment je gère une erreur.

Voir ou contrôleur

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

Donc si je reçois un code 404 de mon modèle (par exemple):

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

Ensuite, je l’attrape dans la vue ou le contrôleur et lève une autre exception que Joomla gérera et affichera 404 pages. Pour tout autre, je montre simplement un message d'erreur générique à l'utilisateur.

Aussi read cette discussion intéressante sur la gestion des erreurs.

12
Dmitry Rekun

La plupart des blocs de code comme celui-ci peuvent simplement être remplacés par enqueueMessage car ils n'agissent pas réellement sur l'erreur et utilisent simplement JError pour les imprimer.

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