データベーストランザクションでの例外/エラーのキャッチ


11

joomla 2.5および3で次の方法を使用してデータベースクエリを実行しています-

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

しかし、$database->getErrorNum()非推奨となっている何らかの理由でクエリが失敗した場合、エラー/例外をどのようにキャッチしますか?

回答:


13

JErrorは、J3.xでは非推奨になりました。PHPの例外のため、ロギングとエラー処理の2つの異なるプログラミング概念が混在しているためです(ロギング側はJLogとして実装されています)。

あなたの正確なケースでは、このSOの答えに示すように、コードをtry / catchブロックでラップしてエラーを取得できます

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

J2.5では機能$database->execute()ないことが明記されていることに注意してください。$database->query()同等のものが必要な場合に使用してください。

Joomla 2.5および3.xでは、JDatabaseオブジェクトメソッド updateRecord()insertRecord()エラーがスローされ、失敗した場合にキャッチできます。

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

Joomla 3.x専用に開発している場合は、SQLトランザクションで try catchブロックを使用して、エラーの詳細を取得することもできます。

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

私のjoomla 2.5.11で$ database-> execute(); joomla 2.5および3の単一コンポーネントを作成しているので問題なく動作しますが、execute()を使用した最初のtry-catchブロックは2.5.11では機能しません。あなたが言ったように、Jdatabaseオブジェクトメソッドは2.5と3.1でしか機能しないため、これを使用しません。
dev-m 14

ええと、奇妙なことに、ドキュメントでは-> execute()は2.5では機能しないと述べられているようです。編集します。JDatabaseオブジェクトのメソッドは、すべてのJ3.Xのバージョンで動作するはずです
codinghands

1
「しかし、execute()を使用した最初のtry-catchブロックは2.5.11では機能しません」...もしあれば、どのようなエラーが発生しますか?
コーディングハンド2014

メッセージはチェックしませんでしたが、falseを返しました。確かにfalseを返さないので、2.5.11サイトのcatchブロックに制御が入りません。
dev-m

PHPがエラーを生成しているかどうかを確認するには、グローバル構成でエラー報告を有効にできますか?
コーディングハンズ14

0

理想的には、peclをインストールしてから適切なJDatabase *クラスを拡張し、以下の実装でJFactory :: getDbo()をオーバーライドして、重要なすべてのdbクエリをtry catchステートメントでラップするための膨大なコード更新の必要性を排除します。

私にとって次善の策は、以下の古い方法と新しい方法のサポートです。

これをどこかに含める

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

次に、このように使用します

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;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.