11

I am using the following way in joomla 2.5 and 3 to execute database query -

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

but how do I catch errors/exceptions if the query fails for any reasons as $database->getErrorNum() is deprecated?

2 Answers 2

13

JError has been deprecated in J3.x, in favour of PHP exceptions, as it intermixed 2 different programming concepts: logging and error handling (the logging side has now been implemented as JLog).

For your exact case, you can wrap your code in a try / catch block to get the error, as shown in this SO answer:

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

Note that $database->execute() is stated to NOT work in J2.5. You should use $database->query() if you need an equivalent.

In Joomla 2.5 and 3.x the JDatabase object methods updateRecord() and insertRecord() also throw errors you can catch if they fail:

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

If you're developing for Joomla 3.x only, you can also use a try catch block with SQL transactions to get the error details:

$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);
}
12
  • in my joomla 2.5.11 $database->execute(); works fine as i am making single component for joomla 2.5 and 3. But your first try-catch block with execute() not works in 2.5.11. As you said Jdatabase object methods only works 2.5 and 3.1 so not gonna use it.So what other methods available to implement this and compatible with both J 2.5 and 3 versions??.
    – dev-m
    Apr 29, 2014 at 15:32
  • Huh, weird, the docs seem to state that ->execute() doesn't work in 2.5. Will edit. JDatabase object methods should work in all J3.X versions Apr 29, 2014 at 15:36
  • 1
    "But your first try-catch block with execute() not works in 2.5.11"... what error do you get, if any? Apr 29, 2014 at 15:48
  • I did not check message but i put a return false; there but it's not returning false for sure so is control not entering in catch block in my 2.5.11 site.
    – dev-m
    Apr 29, 2014 at 16:13
  • Could you enable error reporting in Global Configuration To see if PHP is generating any errors. Apr 29, 2014 at 17:05
0

Ideally install pecl then extend the appropriate JDatabase* class and override JFactory::getDbo() with an implementation of the below to eliminate the need for a squillion code updates to wrap every critical db query in try catch statements.

Next best thing for me is the below support for the old way and the new way:

Include this somewhere

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

Then use it like this

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.