Was ist der richtige Weg für die Ausnahmebehandlung?

20

Im Joomla Core finde ich noch viele Aufrufe wie diesen:

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

JError ist jedoch seit Platform Release 12.1 veraltet. Also, wie soll ich Standard-PHP-Ausnahmen verwenden.

Harald Leithner
quelle
1
Der Unterschied ist, dass sich JError zu PHP-Fehlern verschiebt. Leider ist dies nicht nur ein Ein-Klick-Prozess. Wenn Sie also sicher sind, dass Sie eine Ausnahme bekommen, führen Sie eine try / catch-Anweisung wie in der Antwort unten aus. Wenn Sie sicher sind, dass Sie einen JError bekommen, müssen Sie einen ähnlichen Code wie oben ausführen :)
George Wilson

Antworten:

17

Wie @DmitryRekun sagte, ist hier eine gute Diskussion . Das wichtigste Kriterium dabei ist, welche Art von Fehler haben Sie?

Es gibt zwei Arten von Fehlern:

  1. Wiederherstellbar
  2. Nicht wiederherstellbar.

Der Unterschied lässt sich wie folgt zusammenfassen:

Can I still show the page that was requested, even though this error occurred?
  • Ja? - Wiederherstellbar
  • Nein? - Nicht wiederherstellbar

Jetzt wissen wir, womit wir es zu tun haben. Was sollte man tun?

Wenn der Fehler nicht behoben werden kann, möchten Sie ihn auf eine Fehlerseite umleiten, anstatt mit der angeforderten Seite fortzufahren . Das ist so einfach wie das Folgende:

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

Exceptionist eine Klasse, die zwei Parameter akzeptiert, eine Nachricht und einen Code. Es wird empfohlen, die HTTP-Antwortcodes zu verwenden, wenn sie zu Ihrem Szenario passen.

Wenn der Fehler behoben werden kann, möchten Sie dem Endbenutzer wahrscheinlich nur eine Nachricht anzeigen, während ihm die angeforderte Seite angezeigt wird. Dies bedeutet normalerweise, dass Sie eine Nachricht für die Anwendung in die Warteschlange stellen müssen:

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

enqueueMessageEs werden zwei Parameter verwendet, die Fehlermeldung und ein Nachrichtentyp. Mehr Infos hier (unten).


Es gibt auch eine dritte Situation, die zumindest für mich ziemlich häufig vorkommt. Joomla löst Ausnahmen für verschiedene Fehler aus (z. B. einen Datenbankabfragefehler). Dies bedeutet, dass Joomla denkt, dass dieser Fehler nicht behebbar ist. Möglicherweise möchten Sie jedoch trotzdem fortfahren. (Wenn ich zum Beispiel eine Tabelle bei der Aktualisierung meiner Erweiterung ändere, kann ich einfach die ALTERAbfrage ausführen , die eine Ausnahme auslöst, wenn die Tabelle zuvor geändert wurde.)

In diesem Fall möchten Sie den Code, der möglicherweise eine Ausnahme auslöst, in einen try ... catch-Abschnitt einschließen:

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
}

Beachten Sie, dass Sie den nicht behebbaren Fehler "abfangen" und das System zur Wiederherstellung zwingen und die angeforderte Seite weiterhin anzeigen.


Addieren Sie all dies und Ihr Fall sollte ein nicht behebbarer Fehler sein. (Ich weiß das, weil Sie danach "false" zurückgegeben haben, also planen Sie wahrscheinlich nicht fortzufahren und geben die Funktion auf.)

Also würde ich das wie folgt umschreiben:

// 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
quelle
Gute Antwort! Aber ich würde mich nicht darauf verlassen, $this->get('Errors')weil es auch veraltet ist.
Dmitry Rekun
Irgendwelche Kommentare zu fehlgeschlagenen Behauptungen, dh internen Fehlern? Ich möchte, dass das Programm bei einer fehlgeschlagenen Behauptung sofort abstirbt. Gibt es eine Joomla-spezifische Möglichkeit, dies zu tun? Im Moment registriere ich einen Handler geltend machen , wenn JDEBUGist true.
Olle Härstedt
12

So gehe ich mit Fehlern um.

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

Wenn ich also einen 404-Code von meinem Modell bekomme (zum Beispiel):

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

Dann fange ich es in der Ansicht oder im Controller ein und werfe eine weitere Ausnahme, die Joomla behandeln und 404-Seite anzeigen wird. Bei allen anderen zeige ich dem Benutzer nur eine allgemeine Fehlermeldung.

Auch liest diese interessante Diskussion über die Fehlerbehandlung.

Dmitry Rekun
quelle
4

Die meisten Codeblöcke dieser Art können einfach durch solche ersetzt werden, enqueueMessageda sie den Fehler nicht tatsächlich behandeln und lediglich JErrorzum Ausdrucken verwenden.

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