Ausnahme / Fehler in Datenbanktransaktion abfangen


11

Ich verwende die folgenden Methoden in Joomla 2.5 und 3, um eine Datenbankabfrage auszuführen:

$database = JFactory::getDBO();
$database->setQuery
$database->execute();

Aber wie kann ich Fehler / Ausnahmen abfangen, wenn die Abfrage aus $database->getErrorNum()veralteten Gründen fehlschlägt ?

Antworten:


13

JError wurde in J3.x zugunsten von PHP-Ausnahmen veraltet, da zwei verschiedene Programmierkonzepte vermischt wurden : Protokollierung und Fehlerbehandlung (die Protokollierungsseite wurde jetzt als JLog implementiert ).

Für Ihren genauen Fall können Sie Ihren Code in einen Try / Catch-Block einschließen, um den Fehler zu erhalten, wie in dieser SO-Antwort gezeigt :

try {
    ...
    $db->setQuery($query);
    $result = $db->loadResult();
}
catch (Exception $e){
    echo $e->getMessage();
}

Beachten Sie, dass $database->execute()zu angegebenen NICHT Arbeit in J2.5 . Sie sollten verwenden, $database->query()wenn Sie ein Äquivalent benötigen.

In Joomla 2.5 und 3.x können Sie die JDatabaseObjektmethoden updateRecord() und insertRecord()auch Fehler auslösen, die Sie abfangen können, wenn sie fehlschlagen:

try {
    JFactory::getDbo()->updateObject('#_table_name', $data);
} catch (Exception $e) {
    //...handle the exception
}

Wenn Sie nur für Joomla 3.x entwickeln, können Sie auch einen try catch-Block mit SQL-Transaktionen verwenden , um die Fehlerdetails abzurufen:

$db = JFactory::getDbo();

try {
    $db->transactionStart();

    $query = $db->getQuery(true);

    $values = array($db->quote('TEST_CONSTANT'), $db->quote('Custom'), $db->quote('/path/to/translation.ini'));

    $query->insert($db->quoteName('#__overrider'));
    $query->columns($db->quoteName(array('constant', 'string', 'file')));
    $query->values(implode(',',$values));

    $db->setQuery($query);
    $result = $db->execute();

    $db->transactionCommit();
}
catch (Exception $e) {
    // catch any database errors.
    $db->transactionRollback();
    JErrorPage::render($e);
}

in meinem joomla 2.5.11 $ database-> execute (); funktioniert gut, da ich eine einzelne Komponente für Joomla 2.5 und 3 mache. Aber Ihr erster Try-Catch-Block mit execute () funktioniert nicht in 2.5.11. Wie Sie sagten, funktionieren die Jdatabase-Objektmethoden nur mit 2.5 und 3.1, werden sie also nicht verwenden. Welche anderen Methoden stehen zur Implementierung zur Verfügung und sind mit den Versionen J 2.5 und 3 kompatibel?
— Dev-M

Huh, komisch, die Dokumente scheinen zu sagen, dass -> execute () in 2.5 nicht funktioniert. Wird bearbeitet. JDatabase-Objektmethoden sollten in allen J3.X-Versionen
— funktionieren

1
"Aber Ihr erster Try-Catch-Block mit execute () funktioniert in 2.5.11 nicht." ... Welchen Fehler erhalten Sie, wenn überhaupt?
— Codinghands

Ich habe die Nachricht nicht überprüft, aber eine falsche Rückgabe eingegeben. dort, aber es gibt sicher nicht false zurück, so dass die Kontrolle nicht in den catch-Block auf meiner 2.5.11-Site eingeht.
— Dev-M

Könnten Sie die Fehlerberichterstattung in der globalen Konfiguration aktivieren, um festzustellen, ob PHP Fehler generiert?
— Codinghands

0

Installieren Sie im Idealfall pecl, erweitern Sie dann die entsprechende JDatabase * -Klasse und überschreiben Sie JFactory :: getDbo () mit der folgenden Implementierung, um zu vermeiden, dass eine Billion Code-Updates erforderlich sind, um jede kritische Datenbankabfrage in try catch-Anweisungen zu verpacken.

Das nächstbeste für mich ist die folgende Unterstützung für den alten und den neuen Weg:

Fügen Sie dies irgendwo hinzu

class jDbUtils
{
    protected static $dbErrorMessage = '';

    public static function stupidJ3CatchDatabaseExecute($db, $cmd, $report = false) {
        self::$dbErrorMessage = '';
        try {
            $res = $db->$cmd();
            // legacy db error support
            if (method_exists($db, 'getErrorNum') && $db->getErrorNum())
                throw new Exception($db->getErrorMsg());
            return $res;
        } catch(Exception $e) {
            self::$dbErrorMessage = $e->getMessage();
            if ($report)
                self::reportIfDbError();
            return false;
        }
    }

    public static function reportIfDbError()
    {
        if (self::$dbErrorMessage) {
            JFactory::getApplication()->enqueueMessage(self::$dbErrorMessage, 'error');
            return true;
        }
    }
}

Dann benutze es so

function someDbInteraction(){
    $db = JFactory::getDbo();
    $db->setQuery('SELECT no_such_col FROM no_such_table LIMIT 1');
    $res = jDbUtils::stupidJ3CatchDatabaseExecute($db, 'loadResult');
    if (jDbUtils::reportIfDbError())
        return false;
    // do more processing
    return $res;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.