it-swarm-vi.com

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

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 vì $database->getErrorNum() không được dùng nữa?

11
dev-m

JError đã bị từ chối trong J3.x, ủng hộ PHP ngoại lệ, vì nó xen kẽ 2 khái niệm lập trình khác nha : ghi nhật ký và xử lý lỗi (hiện tại đã đăng nhập thực hiện như 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 this SO answer :

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

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

Trong Joomla 2.5 và 3.x, JDatabase phương thức đối tượngupdateRecord()insertRecord() cũng ném các lỗi bạn có thể bắt 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 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);
}
13
codinghands

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ã hàng triệu để 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;
}
0
ekerner