Qual è il modo corretto di gestire le eccezioni?


20

Nel core di Joomla trovo ancora molte chiamate come questa:

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

Ma JError è obsoleto dalla versione 12.1 della piattaforma. Quindi, come dovrei usare le eccezioni PHP standard.


1
La differenza sta passando da JError a PHP Error purtroppo non è semplicemente un processo. Quindi, se sei sicuro di ottenere un'eccezione, fai una dichiarazione try / catch come nella risposta qui sotto. Se sei sicuro di ottenere un JError, allora devi fare un codice simile a quello sopra :)
George Wilson,

Risposte:


17

Come ha detto @DmitryRekun, una buona discussione è qui . Il pezzo chiave da considerare in tutto questo è che tipo di errore hai?

Esistono due tipi di errori:

  1. Recuperabile
  2. Non recuperabile.

La differenza che tendo a riassumere come segue:

Can I still show the page that was requested, even though this error occurred?
  • Sì? - Recuperabile
  • No? - Non recuperabile

Ora che sappiamo con cosa abbiamo a che fare. Cosa dovresti fare

Se l'errore non è recuperabile, si desidera reindirizzarli a una pagina di errore invece di continuare sulla pagina richiesta . Questo è semplice come il seguente:

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

Exceptionè una classe che accetta due parametri, un messaggio e un codice. Si consiglia di provare a utilizzare i codici di risposta HTTP se si adattano allo scenario.

Se l'errore è ripristinabile, è probabile che tu voglia solo visualizzare un messaggio all'utente finale, mostrando comunque la pagina richiesta. Ciò significa in genere che è necessario "accodare" un messaggio per l'applicazione:

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

enqueueMessageaccetta due parametri, il messaggio di errore e un tipo di messaggio. Maggiori informazioni qui (in basso).


C'è anche una terza situazione che si verifica abbastanza spesso per me almeno. Joomla genererà eccezioni per diversi errori (come un errore di query del database). Ciò significa che Joomla pensa che questo errore sia irrecuperabile. Tuttavia, potresti voler continuare comunque. (Ad esempio, se sto modificando una tabella durante l'aggiornamento della mia estensione, posso semplicemente eseguire la ALTERquery, che genererà un'eccezione se la tabella è stata precedentemente modificata.)

In tal caso, vuoi racchiudere il codice che potrebbe generare un'eccezione in una sezione 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
}

Si noti che ciò che si sta facendo è "rilevare" l'errore irrecuperabile e forzare il sistema a ripristinare e continuare a mostrare la pagina richiesta.


Aggiungi tutto questo e il tuo caso dovrebbe essere un errore irrecuperabile. (Lo so perché hai "return false" in seguito, quindi probabilmente non hai intenzione di continuare e stai rinunciando alla funzione.)

Quindi riscriverei questo come segue:

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

Buona risposta! Ma non farei affidamento $this->get('Errors')perché è anche deprecato.
Dmitry Rekun,

Qualche commento su asserzioni fallite, ovvero errori interni? Vorrei che il programma morisse immediatamente a causa di un'affermazione fallita: esiste un modo specifico per Joomla per farlo? Al momento, registro un gestore dell'asserzione se lo JDEBUGè true.
Olle Härstedt,

12

Ecco come sto gestendo un errore.

Visualizza o controller

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

Quindi se ottengo un codice 404 dal mio modello (ad esempio):

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

Poi lo vedo nella vista o nel controller e lancio un'altra eccezione che Joomla gestirà e visualizzerà 404 pagine. Per qualsiasi altro mostro solo un messaggio di errore generico all'utente.

Leggi anche questa interessante discussione sulla gestione degli errori.


4

La maggior parte dei blocchi di codice come questo può essere semplicemente sostituita enqueueMessagedal momento che in realtà non agiscono sull'errore e semplicemente utilizzano JErrorper stamparli.

// Check for errors.
if (count($errors = $this->get('Errors'))) {
    foreach($errors as $error) {
        JFactory::getApplication()->enqueueMessage($error, 'error');
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.