Menangkap pengecualian / kesalahan dalam transaksi basis data

11

Saya menggunakan cara berikut di joomla 2.5 dan 3 untuk mengeksekusi query database -

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

tetapi bagaimana cara menangkap kesalahan / pengecualian jika kueri gagal karena alasan apa pun karena $database->getErrorNum()sudah usang?

dev-m
sumber

Jawaban:

13

JError telah ditinggalkan dalam J3.x, mendukung pengecualian PHP, karena menggabungkan 2 konsep pemrograman yang berbeda : logging dan penanganan kesalahan (sisi logging sekarang telah diimplementasikan sebagai JLog ).

Untuk kasus yang tepat, Anda dapat membungkus kode Anda dalam blok coba / tangkap untuk mendapatkan kesalahan, seperti yang ditunjukkan dalam jawaban SO ini :

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

Catatan yang $database->execute()dinyatakan TIDAK bekerja di J2.5 . Anda harus menggunakan $database->query()jika Anda membutuhkan yang setara.

Di Joomla 2.5 dan 3.x JDatabasemetode objek updateRecord() dan insertRecord()juga melempar kesalahan yang dapat Anda tangkap jika gagal:

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

Jika Anda hanya mengembangkan untuk Joomla 3.x, Anda juga dapat menggunakan blok coba tangkap dengan transaksi SQL untuk mendapatkan detail kesalahan:

$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);
}
tangan coding
sumber
di joomla saya 2.5.11 $ database-> execute (); berfungsi dengan baik karena saya membuat komponen tunggal untuk joomla 2.5 dan 3. Tapi blok try-catch pertama Anda dengan execute () tidak berfungsi di 2.5.11. Seperti yang Anda katakan metode objek Jdatabase hanya bekerja 2,5 dan 3,1 sehingga tidak akan menggunakannya. Jadi metode lain apa yang tersedia untuk mengimplementasikan ini dan kompatibel dengan kedua versi J 2.5 dan 3 ??.
dev-m
Huh, aneh, dokumen sepertinya menyatakan bahwa -> execute () tidak berfungsi di 2.5. Akan diedit. Metode objek JDatabase harus bekerja di semua versi
J3.X
1
"Tapi blok try-catch pertama Anda dengan eksekusi () tidak berfungsi di 2.5.11" ... kesalahan apa yang Anda dapatkan, jika ada?
coding tangan
Saya tidak memeriksa pesan tetapi saya mengembalikan false; ada tapi itu tidak mengembalikan false pasti kontrol tidak masuk dalam blok tangkap di situs 2.5.11 saya.
dev-m
Bisakah Anda mengaktifkan pelaporan kesalahan dalam Konfigurasi Global Untuk melihat apakah PHP menghasilkan kesalahan.
coding tangan
0

Idealnya instal pecl kemudian perpanjang kelas JDatabase * yang sesuai dan ganti JFactory :: getDbo () dengan implementasi di bawah ini untuk menghilangkan kebutuhan akan pembaruan kode triliunan untuk membungkus setiap kueri db penting dalam pernyataan coba tangkap.

Hal terbaik berikutnya bagi saya adalah dukungan di bawah ini untuk cara lama dan cara baru:

Sertakan ini di suatu tempat

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

Kemudian gunakan seperti ini

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
sumber