Captura de exceção / erro na transação do banco de dados

11

Estou usando a seguinte maneira no joomla 2.5 e 3 para executar a consulta ao banco de dados -

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

mas como capturar erros / exceções se a consulta falhar por algum motivo, como $database->getErrorNum()foi preterido?

dev-m
fonte

Respostas:

13

O JError foi descontinuado no J3.x, em favor das exceções do PHP, pois misturou 2 conceitos diferentes de programação : registro e tratamento de erros (o lado do registro agora foi implementado como JLog ).

Para o seu caso exato, você pode agrupar seu código em um bloco try / catch para obter o erro, conforme mostrado nesta resposta do SO :

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

Observe que $database->execute()é indicado para NÃO funcionar no J2.5 . Você deve usar $database->query()se precisar de um equivalente.

No Joomla 2.5 e 3.xe os JDatabasemétodos de objeto updateRecord() e insertRecord()também lançam erros que você pode capturar se falharem:

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

Se você está desenvolvendo apenas para o Joomla 3.x, também pode usar um bloco try catch com transações SQL para obter os detalhes do erro:

$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);
}
codinghands
fonte
no meu joomla 2.5.11 $ database-> execute (); funciona bem como eu estou criando um componente para o joomla 2.5 e 3. Mas o seu primeiro bloco try-catch com execute () não funciona no 2.5.11. Como você disse, os métodos de objeto do Jdatabase funcionam apenas com 2.5 e 3.1, portanto não serão utilizados. Então, quais outros métodos disponíveis para implementar isso e compatíveis com as versões J 2.5 e 3 ??
Dev-m #
Estranho, os documentos parecem afirmar que -> execute () não funciona no 2.5. Irá editar. Métodos de objetos JDatabase deve funcionar em todas as versões J3.X
codinghands
1
"Mas seu primeiro bloco try-catch com execute () não funciona no 2.5.11" ... que erro você recebe, se houver?
Codinghands 29/04
Não verifiquei a mensagem, mas coloquei um retorno false; lá, mas ele não está retornando false, com certeza, assim como o controle não está entrando no bloco catch no meu site 2.5.11.
Dev-m
Você pode habilitar o relatório de erros na Configuração Global Para ver se o PHP está gerando algum erro.
Codinghands
0

O ideal é instalar o pecl, estender a classe JDatabase * apropriada e substituir JFactory :: getDbo () com uma implementação abaixo para eliminar a necessidade de um milhão de atualizações de código para agrupar todas as consultas críticas do banco de dados nas instruções try catch.

A melhor coisa para mim é o suporte abaixo para a maneira antiga e a nova:

Inclua isso em algum lugar

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

Então use-o assim

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