Captura de excepción / error en la transacción de la base de datos

11

Estoy usando la siguiente manera en joomla 2.5 y 3 para ejecutar la consulta de la base de datos:

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

pero, ¿cómo puedo detectar errores / excepciones si la consulta falla por algún motivo que $database->getErrorNum()está en desuso?

dev-m
fuente

Respuestas:

13

JError ha quedado en desuso en J3.x, a favor de las excepciones de PHP, ya que entremezcló 2 conceptos de programación diferentes : registro y manejo de errores (el lado de registro ahora se ha implementado como JLog ).

Para su caso exacto, puede envolver su código en un bloque try / catch para obtener el error, como se muestra en esta respuesta SO :

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

Tenga en cuenta que $database->execute()se indica que NO funciona en J2.5 . Debe usarlo $database->query()si necesita un equivalente.

En Joomla 2.5 y 3.x los JDatabasemétodos de objeto updateRecord() y insertRecord()también arrojan errores que puede detectar si fallan:

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

Si está desarrollando solo para Joomla 3.x, también puede usar un bloque try catch con transacciones SQL para obtener los detalles del error:

$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
fuente
en mi joomla 2.5.11 $ database-> execute (); funciona bien ya que estoy haciendo un solo componente para joomla 2.5 y 3. Pero su primer bloque try-catch con execute () no funciona en 2.5.11. Como dijiste, los métodos de objetos Jdatabase solo funcionan 2.5 y 3.1, por lo que no los usaré. Entonces, ¿qué otros métodos están disponibles para implementar esto y son compatibles con las versiones J 2.5 y 3?
dev-m
Huh, raro, los documentos parecen indicar que -> execute () no funciona en 2.5. Se editará Los métodos de objeto JDatabase deberían funcionar en todas las versiones de
J3.X
1
"Pero su primer bloque try-catch con execute () no funciona en 2.5.11" ... ¿qué error obtiene, si lo tiene?
codinghands
No verifiqué el mensaje pero puse un retorno falso; allí, pero no devuelve falso, por lo que el control no ingresa en el bloque catch en mi sitio 2.5.11.
dev-m
¿Podría habilitar el informe de errores en la Configuración global? Para ver si PHP está generando algún error.
codinghands
0

Idealmente, instale pecl, luego extienda la clase JDatabase * apropiada y anule JFactory :: getDbo () con una implementación de lo siguiente para eliminar la necesidad de actualizaciones de código de un billón para envolver cada consulta de db crítica en las declaraciones de try catch.

Lo mejor para mí es el siguiente soporte para la forma antigua y la nueva:

Incluye esto en alguna parte

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

Entonces úsalo así

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
fuente