Bắt ngoại lệ / lỗi trong giao dịch cơ sở dữ liệu


11

Tôi đang sử dụng cách sau trong j Joomla 2.5 và 3 để thực hiện truy vấn cơ sở dữ liệu -

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

nhưng làm cách nào để bắt lỗi / ngoại lệ nếu truy vấn không thành công vì bất kỳ lý do nào $database->getErrorNum()bị phản đối?

Câu trả lời:


13

JError đã không được chấp nhận trong J3.x, vì các ngoại lệ của PHP, vì nó xen kẽ 2 khái niệm lập trình khác nhau : ghi nhật ký và xử lý lỗi (phía đăng nhập hiện đã được triển khai dưới dạng JLog ).

Đối với trường hợp chính xác của bạn, bạn có thể bọc mã của mình trong khối thử / bắt để nhận lỗi, như được hiển thị trong câu trả lời SO này :

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

Lưu ý rằng $database->execute()được nêu là KHÔNG hoạt động trong J2.5 . Bạn nên sử dụng $database->query()nếu bạn cần một tương đương.

Trong Joomla 2.5 và 3.x, các JDatabasephương thức đối tượng updateRecord()insertRecord()cũng đưa ra các lỗi bạn có thể mắc phải nếu chúng thất bại:

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

Nếu bạn chỉ phát triển cho Joomla 3.x, bạn cũng có thể sử dụng khối thử bắt với các giao dịch SQL để nhận chi tiết lỗi:

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

trong cơ sở dữ liệu j Joomla 2.5.11 $ của tôi-> exec (); hoạt động tốt vì tôi đang tạo một thành phần duy nhất cho j Joomla 2.5 và 3. Nhưng khối thử bắt đầu tiên của bạn với exec () không hoạt động trong 2.5.11. Như bạn đã nói các phương thức đối tượng Jdatabase chỉ hoạt động 2.5 và 3.1 vì vậy sẽ không sử dụng nó. Vì vậy, các phương thức khác có sẵn để thực hiện điều này và tương thích với cả hai phiên bản J 2.5 và 3 ??.
dev-m

Huh, lạ thật, các tài liệu dường như nói rằng -> exec () không hoạt động trong 2.5. Sẽ chỉnh sửa. Các phương thức đối tượng JDatabase sẽ hoạt động trong tất cả các phiên bản
J3.X

1
"Nhưng khối thử bắt đầu tiên của bạn với exec () không hoạt động trong 2.5.11" ... bạn gặp lỗi gì, nếu có?
mã hóa

Tôi đã không kiểm tra tin nhắn nhưng tôi đã trả lại sai; ở đó nhưng nó không trả về sai vì chắc chắn là kiểm soát không nhập vào khối bắt trong trang 2.5.11 của tôi.
dev-m

Bạn có thể bật báo cáo lỗi trong Cấu hình toàn cầu để xem PHP có tạo ra bất kỳ lỗi nào không.
mã hóa

0

Cài đặt pecl một cách lý tưởng sau đó mở rộng lớp JDatabase * thích hợp và ghi đè JFactory :: getDbo () bằng cách triển khai bên dưới để loại bỏ sự cần thiết phải cập nhật mã tỷ để bao gồm mọi truy vấn db quan trọng trong các câu lệnh thử.

Điều tốt nhất tiếp theo đối với tôi là sự hỗ trợ dưới đây cho cách cũ và cách mới:

Bao gồm cái này ở đâu đó

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

Sau đó sử dụng nó như thế này

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