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 ?

dev-m
quelle

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);
}
Codierungshände
quelle
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;
}
ekerner
quelle