Apa cara yang benar untuk penanganan pengecualian?

20

Di Joomla core saya menemukan masih banyak panggilan seperti ini:

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

Namun JError sudah tidak digunakan lagi sejak Platform merilis 12.1. Jadi bagaimana saya harus menggunakan pengecualian PHP standar.

Harald Leithner
sumber
1
Perbedaannya adalah pindah dari JError ke Kesalahan PHP bukan hanya proses satu klik sayangnya. Jadi, jika Anda yakin akan mendapatkan pengecualian maka lakukan pernyataan coba-coba seperti pada jawaban di bawah ini. Jika Anda yakin akan mendapatkan JError maka Anda perlu melakukan kode yang mirip dengan yang di atas :)
George Wilson

Jawaban:

17

Seperti yang dikatakan @DmitryRekun, diskusi yang baik ada di sini . Bagian penting untuk dipertimbangkan dalam semua ini adalah jenis kesalahan apa yang Anda miliki?

Ada dua jenis kesalahan:

  1. Dapat dipulihkan
  2. Tidak dapat dipulihkan.

Perbedaannya saya cenderung menyimpulkan sebagai berikut:

Can I still show the page that was requested, even though this error occurred?
  • Iya nih? - Dapat dipulihkan
  • Tidak? - Tidak bisa dipulihkan

Sekarang kita tahu apa yang sedang kita hadapi. Apa yang harus kamu lakukan

Jika kesalahan tidak dapat dipulihkan, Anda ingin mengarahkan mereka ke halaman kesalahan alih-alih melanjutkan ke halaman yang diminta . Itu sesederhana berikut ini:

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

Exceptionadalah kelas yang mengambil dua parameter, pesan dan kode. Disarankan untuk mencoba menggunakan Kode Respons HTTP jika sesuai dengan skenario Anda.

Jika kesalahan dapat dipulihkan, Anda mungkin hanya ingin menampilkan pesan kembali ke pengguna akhir sambil tetap menunjukkan kepada mereka halaman yang mereka minta. Ini biasanya berarti bahwa Anda harus 'mengirim pesan' untuk aplikasi:

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

enqueueMessagemengambil dua parameter, pesan kesalahan dan jenis pesan. Info lebih lanjut di sini (di bagian bawah).


Ada juga situasi ketiga yang terjadi cukup sering bagi saya setidaknya. Joomla akan memberikan pengecualian untuk kesalahan yang berbeda (seperti kesalahan permintaan basis data). Ini berarti bahwa Joomla berpikir bahwa kesalahan ini tidak dapat dipulihkan. Namun, Anda mungkin ingin melanjutkan. (Misalnya, jika saya mengubah tabel saat memperbarui ekstensi saya, saya bisa menjalankan ALTERkueri, yang akan mengeluarkan pengecualian jika tabel sebelumnya telah diubah.)

Dalam hal ini, Anda ingin membungkus kode yang mungkin membuang pengecualian di bagian coba ... catch:

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
}

Perhatikan bahwa apa yang Anda lakukan adalah "menangkap" kesalahan yang tidak dapat dipulihkan dan memaksa sistem untuk memulihkan dan terus menampilkan halaman yang diminta.


Tambahkan semua ini dan kasing Anda harus merupakan kesalahan yang tidak dapat dipulihkan. (Saya tahu ini karena Anda memiliki 'return false' setelahnya, jadi Anda kemungkinan tidak berencana untuk melanjutkan dan menyerah pada fungsi.)

Jadi saya akan menulis ulang ini sebagai berikut:

// 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
sumber
Jawaban yang bagus! Tapi saya tidak akan bergantung $this->get('Errors')karena itu juga sudah usang.
Dmitry Rekun
Adakah komentar tentang pernyataan yang gagal, yaitu kesalahan internal? Saya ingin program untuk segera mati pada pernyataan yang gagal - apakah ada cara khusus Joomla untuk melakukan ini? Saat ini saya mendaftarkan penangan tegas jika JDEBUGada true.
Olle Härstedt
12

Inilah cara saya mengelola kesalahan.

Lihat atau Kontroler

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

Jadi jika saya mendapatkan kode 404 dari Model saya (misalnya):

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

Lalu saya menangkapnya di tampilan atau pengontrol dan melemparkan satu Pengecualian lagi yang akan ditangani Joomla dan akan menampilkan 404 halaman. Untuk yang lain saya hanya menunjukkan beberapa pesan kesalahan umum kepada pengguna.

Baca juga diskusi menarik tentang penanganan kesalahan ini.

Dmitry Rekun
sumber
4

Sebagian besar blok kode seperti ini dapat dengan mudah diganti enqueueMessagekarena mereka tidak benar-benar bertindak atas kesalahan dan hanya menggunakan JErroruntuk mencetaknya.

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