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


20

Dans le noyau Joomla, 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 obsolète depuis la version 12.1 de la plateforme. Alors, comment dois-je utiliser les exceptions PHP standard.


1
Malheureusement, la différence entre JError et PHP Errors n'est pas simplement un processus en un clic. Donc, si vous êtes sûr d'obtenir une exception, faites une déclaration try / catch comme dans la réponse ci-dessous. Si vous êtes sûr que vous allez obtenir un JError, vous devez faire un code similaire à celui ci-dessus :)
George Wilson

Réponses:


17

Comme l'a dit @DmitryRekun, une bonne discussion est ici . L'élément clé à considérer dans tout cela est quel type d'erreur avez-vous?

Il existe 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 de quoi il s'agit. Que devrais tu faire?

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

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

Exceptionest une classe qui prend deux paramètres, un message et un code. Il est recommandé d'essayer d'utiliser les 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 lui montrant la page 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');

enqueueMessageprend 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 pour moi au moins. Joomla lèvera des exceptions pour différentes erreurs (comme 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 de toute façon. (Par exemple, si je modifie une table lors de la mise à jour de mon extension, je peux simplement exécuter la ALTERrequête, qui lèvera une exception si la table a déjà été modifiée.)

Dans ce cas, vous voulez encapsuler le code qui pourrait lever 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 ce que vous faites consiste à "détecter" l'erreur irrécupérable et à forcer 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 'retourné faux' par la suite, vous n'avez donc probablement pas l'intention de continuer et 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.
}

Bonne réponse! Mais je ne m'y fierais pas $this->get('Errors')car il est également obsolète.
Dmitry Rekun

Y a-t-il des commentaires sur des assertions ayant échoué, c'est-à-dire des erreurs internes? J'aimerais que le programme meure immédiatement après une affirmation ratée - existe-t-il une façon spécifique à Joomla de le faire? En ce moment, j'enregistre un gestionnaire d'assertions si JDEBUGc'est le cas true.
Olle Härstedt,

12

Voici comment je gère une erreur.

Vue 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 jette une autre exception que Joomla gérera et affichera la page 404. Pour tout autre, je montre simplement un message d'erreur générique à l'utilisateur.

Lisez également cette discussion intéressante sur la gestion des erreurs.


4

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

// Check for errors.
if (count($errors = $this->get('Errors'))) {
    foreach($errors as $error) {
        JFactory::getApplication()->enqueueMessage($error, 'error');
    }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.