Cách chính xác để xử lý ngoại lệ là gì?


20

Trong lõi Joomla tôi vẫn thấy nhiều cuộc gọi như thế này:

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

Nhưng JError không được chấp nhận kể từ khi phát hành Nền tảng 12.1. Vì vậy, làm thế nào tôi nên sử dụng các ngoại lệ PHP tiêu chuẩn.


1
Sự khác biệt đang chuyển từ JError sang PHP Lỗi không chỉ đơn giản là quá trình một lần nhấp. Vì vậy, nếu bạn chắc chắn rằng bạn sẽ có một ngoại lệ, hãy thực hiện một câu lệnh thử / bắt như trong câu trả lời dưới đây. Nếu bạn chắc chắn rằng bạn sẽ nhận được JError thì bạn cần phải thực hiện mã tương tự như trên :)
George Wilson

Câu trả lời:


17

Như @DmitryRekun đã nói, một cuộc thảo luận tốt ở đây . Mấu chốt cần xem xét trong tất cả những điều này là loại lỗi nào bạn có?

Có hai loại lỗi:

  1. Có thể phục hồi
  2. Không thể phục hồi.

Sự khác biệt tôi có xu hướng tổng hợp như sau:

Can I still show the page that was requested, even though this error occurred?
  • Vâng? - Có thể phục hồi
  • Không? - Không thể phục hồi

Bây giờ chúng tôi biết những gì chúng ta đang đối phó. Những gì bạn nên làm?

Nếu lỗi không thể phục hồi, bạn muốn chuyển hướng chúng đến một trang lỗi thay vì tiếp tục đến trang được yêu cầu . Điều đó đơn giản như sau:

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

Exceptionlà một lớp có hai tham số, một thông điệp và một mã. Bạn nên thử sử dụng Mã phản hồi HTTP nếu chúng phù hợp với kịch bản của bạn.

Nếu lỗi có thể phục hồi, có thể bạn chỉ muốn hiển thị thông báo lại cho người dùng cuối trong khi vẫn hiển thị cho họ trang mà họ yêu cầu. Điều này thường có nghĩa là bạn nên 'enqueue' một tin nhắn cho ứng dụng:

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

enqueueMessagecó hai tham số, thông báo lỗi và một loại thông báo. Thêm thông tin ở đây (ở phía dưới).


Ngoài ra còn có một tình huống thứ ba xảy ra khá thường xuyên đối với tôi ít nhất. Joomla sẽ đưa ra các ngoại lệ cho các lỗi khác nhau (chẳng hạn như lỗi truy vấn cơ sở dữ liệu). Điều này có nghĩa là Joomla nghĩ rằng lỗi này là không thể phục hồi. Tuy nhiên, dù sao bạn cũng có thể muốn tiếp tục. (Ví dụ: nếu tôi thay đổi bảng khi cập nhật tiện ích mở rộng của mình, tôi chỉ có thể chạy ALTERtruy vấn, sẽ đưa ra một ngoại lệ nếu bảng đó đã bị thay đổi trước đó.)

Trong trường hợp đó, bạn muốn bọc mã có thể đưa ra một ngoại lệ trong phần thử ... bắt:

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
}

Lưu ý rằng những gì bạn đang làm là "bắt" lỗi không thể phục hồi và buộc hệ thống khôi phục và tiếp tục hiển thị trang được yêu cầu.


Thêm tất cả điều này và trường hợp của bạn sẽ là một lỗi không thể phục hồi. (Tôi biết điều này bởi vì bạn đã 'trả về false' sau đó, vì vậy bạn có thể không có kế hoạch tiếp tục và đang từ bỏ chức năng.)

Vì vậy, tôi sẽ viết lại như sau:

// 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.
}

Câu trả lời tốt! Nhưng tôi sẽ không dựa vào $this->get('Errors')vì nó cũng không được chấp nhận.
Dmitry Rekun

Bất kỳ ý kiến ​​về xác nhận thất bại, đó là, lỗi nội bộ? Tôi muốn chương trình chết ngay lập tức khi xác nhận thất bại - có cách nào cụ thể cho Joomla để làm việc này không? Hiện tại tôi đăng ký một trình xử lý khẳng định nếu JDEBUGtrue.
Olle Härstedt

12

Đây là cách tôi quản lý một lỗi.

Xem hoặc điều khiển

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

Vì vậy, nếu tôi nhận được mã 404 từ Mô hình của mình (ví dụ):

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

Sau đó, tôi bắt nó trong chế độ xem hoặc trình điều khiển và ném thêm một Ngoại lệ mà Joomla sẽ xử lý và sẽ hiển thị trang 404. Đối với bất kỳ khác, tôi chỉ hiển thị một số thông báo lỗi chung cho người dùng.

Cũng đọc cuộc thảo luận thú vị này về xử lý lỗi.


4

Hầu hết các khối mã như thế này có thể được thay thế đơn giản enqueueMessagevì chúng không thực sự gây ra lỗi và chỉ đơn giản là sử dụng JErrorđể in chúng ra.

// Check for errors.
if (count($errors = $this->get('Errors'))) {
    foreach($errors as $error) {
        JFactory::getApplication()->enqueueMessage($error, 'error');
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.