Вилучення виключення / помилки в транзакції бази даних


11

Я використовую наступний спосіб в Joomla 2.5 і 3 для виконання запиту до бази даних -

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

але як я вловлюю помилки / винятки, якщо запит не спрацьовує з будь-яких причин, як $database->getErrorNum()застарілий?

Відповіді:


13

JError був застарілим у J3.x, на користь винятків PHP, оскільки він змішував 2 різні концепції програмування : ведення журналів та обробку помилок (сторона журналу тепер реалізована як JLog ).

Для вашого точного випадку ви можете загорнути свій код у блок "спробувати", щоб отримати помилку, як показано у цій відповіді "ТАК" :

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

Зауважте, що в J2.5$database->execute() зазначено, що НЕ працює . Ви повинні використовувати, $database->query()якщо вам потрібен еквівалент.

У Joomla 2.5 і 3.x JDatabaseоб'єктні методи, updateRecord() а insertRecord()також викидати помилки, які ви можете виявити, якщо вони не вдаються:

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

Якщо ви розробляєте лише для Joomla 3.x, ви також можете використовувати блок спробу вловлювання для транзакцій SQL, щоб отримати детальну інформацію про помилку:

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

в моїй Joomla 2.5.11 $ database-> Execute (); добре працює, оскільки я роблю однокомпонентний для Joomla 2.5 і 3. Але ваш перший пробний блок з Execute () не працює в 2.5.11. Як ви вже сказали, об'єктні методи Jdatabase працюють лише в 2,5 і 3.1, тому не збираєтесь її використовувати. Отже, які інші методи доступні для реалізації цього і сумісні з обома версіями J 2.5 та 3 ??.
дев-м

Так, дивно, документи здаються, що -> Execute () не працює в 2.5. Відредагуємо. Об'єктні методи JDatabase повинні працювати у всіх версіях
J3.X

1
"Але ваш перший пробний блок з Execute () не працює в 2.5.11" ... яка помилка ви отримуєте, якщо така є?
кодування руками

Я не перевірив повідомлення, але я поставив помилкове повернення; там, але це точно не повертається помилковим, тому контроль не входить у блок лову на моєму сайті 2,5.11.
дев-м

Чи можете ви включити звітування про помилки в глобальній конфігурації, щоб побачити, чи PHP генерує якісь помилки.
кодування руками

0

В ідеалі встановіть pecl, після чого розширіть відповідний клас JDatabase * та замініть JFactory :: getDbo () з реалізацією нижче, щоб усунути необхідність оновлення коду в трилість, щоб обернути кожен критичний запит на db в операторах спробу лову.

Наступне найкраще для мене - це наступна підтримка старого та нового способу:

Включіть це десь

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

Тоді використовуйте його так

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;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.