Transacciones de Codeigniter


Estoy usando transacciones Codeigniter

$this->db->trans_start();
$this->db->query('AN SQL QUERY...');
$this->db->trans_complete();

Esto funciona bien , el problema que tengo es que dentro de trans_start y trans_complete estoy llamando a otras funciones y esas funciones se ocupan de la base de datos por lo que contienen inserciones y actualizaciones y algunas eliminaciones ... ex:

$this->db->trans_start();
 $this->utils->insert_function($data);
 $this->utils->update_function2($test);
$this->db->trans_complete();

Ahora si esas funciones se ejecutan y ocurren algunos errores CodeIgniter no hará una reversión.

¿Cuál es la mejor manera de lidiar con este problema?

La única solución, tengo en mente, es devolver un error de esas funciones y dentro de esas funciones add (trans_stat y trans_complete) Y si devuelve un error test an do $this->db->trans_rollback

Ex:

    $this->db->trans_start();
     $result = $this->utils->insert_function($data);
     if($result === false){
       $this->db->trans_rollback();
     }
    $this->db->trans_complete();

¿Hay una mejor manera de hacer esto?

Actualizar 1:

Como se solicitó una muestra de la función externa que estoy llamando:

   // insert_function contains

    $rec = array(
        'numero' => $numero,
        'transaction_id' => $id,
        'debit' => $product_taxes['amount_without_taxes'],
        'date' => $data['date_transaction'],
    );
    $this->addExerciceAccountingRecords($rec);

  and addExerciceAccountingRecords contains

   function addExerciceAccountingRecords($records) {
    $this->db->insert('transactions_exercices', $records);
    }
Author: Abdulla Nilam, 2013-03-05

5 answers

Usar transactions significa apoyar las bases de datos para insertar datos de forma segura. Así que en Codeigniter escribimos todas las funciones relacionadas con la base de datos en el Modelo no en el Controlador.. Y en su segundo código (que no está funcionando) usted ha apuntado modelo allí.(utils). Tan simple que estoy seguro de que esto no funcionará. Porque no es un insertar datos con modelo y controlador paralelo. La transacción debe ser codificada en el Modelo ( Escribiré en el Modelo en mi respuesta).


Carga este material también

  1. Biblioteca de bases de datos
  2. Clase de modelo
  3. URL helper
  4. Sesión

Supuestos

En tu código has usado $data y $test como array. Así que asumo que hay dos matriz para insertar y actualizar datos.


Sus conjuntos de datos

$data = array(
   'title' => 'My title' ,
   'name' => 'My Name' ,
   'date' => 'My date'
);

$id = 007;
$test = array(
   'title' => $title,
   'name' => $name,
   'date' => $date
);

Su código

$this->db->trans_start(); # Starting Transaction
$this->db->trans_strict(FALSE); # See Note 01. If you wish can remove as well 

$this->db->insert('table_name', $data); # Inserting data

# Updating data
$this->db->where('id', $id);
$this->db->update('table_name', $test); 

$this->db->trans_complete(); # Completing transaction

/*Optional*/

if ($this->db->trans_status() === FALSE) {
    # Something went wrong.
    $this->db->trans_rollback();
    return FALSE;
} 
else {
    # Everything is Perfect. 
    # Committing data to the database.
    $this->db->trans_commit();
    return TRUE;
}

Notas

  1. Por default Codeigniter ejecuta todas las transacciones en Modo Estricto. Cuando el modo estricto está habilitado, si está ejecutando varios grupos de transacciones, si un grupo falla, todos los grupos se revertirán. Si el modo estricto está desactivado, cada grupo es tratados independientemente, lo que significa que un fracaso de un grupo no afectará cualesquiera otros .
 28
Author: Abdulla Nilam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-25 09:00:59

Lo que intenté fue más un truco, pero funcionó para mí.

$this->db->trans_begin();
  $rst1=  $this->utils->insert_function($data);
  $rst2 =  $this->utils->update_function2($test);
if($this->db->trans_status() === FALSE || !isset($rst1) || !isset($rst2)){
   $this->db->trans_rollback();
}else{
   $this->db->trans_commit();
}
 4
Author: Heshan Rajapaksha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-08 23:22:39

Sospecho que el problema tiene que ver con cómo CodeIgniter está manejando los objetos.

Si va a la documentación de CI bajo la sección "Creación de bibliotecas" en:
http://ellislab.com/codeigniter/user-guide/general/creating_libraries.html
y mira la sección relacionada con:

$CI =& get_instance();
$CI->load->helper('url');
$CI->load->library('session');
$CI->config->item('base_url');

En su controlador principal, ha cargado/instanciado la clase de base de datos ya sea usando carga automática o cargando explícitamente la clase.

A continuación, seguir adelante y abrir la transacción, y luego, accede a su base de datos funciones a través de su biblioteca utils.

Sin embargo, una vez que use $this-db en su biblioteca, en realidad está accediendo a otra copia de la instancia de la base de datos, NO a la que está asociada con su transacción.

Para acceder a la misma instancia, necesita usar la función get_instance ().

Creo que eso debería solucionar tu problema. Su estilo de codificación original para separar la función en varios módulos es excelente. Simplemente necesitas para entender este detalle adicional.

Por favor, intente confirmar que la reversión funciona como espera.

Las tripas del código consisten en el siguiente controlador:

$this->db->trans_start();
$this->User_profile_m->create_new_user_profile();
$this->User_profile_m->create_new_user();
$this->db->trans_complete(); 

Y un modelo simple user_profile_m para tratar la persistencia de datos:

function create_new_user()
{
    $data['user_name_usr'] = $this->input->post('user_name');
    $data['create_date_usr'] = NULL;

    $this->db->insert('user_usr', $data);  
}

function create_new_user_profile()
{
    $data['user_name_pro'] = $this->input->post('user_name');
    $data['user_description_pro'] = $this->input->post('user_description');
    $data['create_date_pro'] = NULL;

    $this->db->insert('user_profile_pro', $data);  
}

Esencialmente, la demostración intenta hacer dos inserciones (una en cada una de las dos tablas). Si un inserto falla, el otro se revierte.

Construí esto en CodeIgniter 2.1.3 y puedo hacer los archivos de la aplicación disponible a través de GitHub o zip para arriba y enviarlos a usted.

 3
Author: Marc Audet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-27 01:59:42


Nota: Asegúrese de usar $this->db->trans_begin() cuando ejecute transacciones manuales, NO $this->db->trans_start().

$this -> db -> trans_begin(); 
$this -> utils -> insert_function ( $data );
$this -> utils -> update_function2 ( $test ); 
$this -> db -> trans_complete ();

Certificar en caso de utilizar MySQL, utilizar en formato InnoDB

 2
Author: Diego,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-30 15:07:25

Pruebe este procedimiento. Realmente funciona para mí:)

$this->db->trans_start();
   $this->utils->insert_function($data);
   $this->utils->update_function2($test);
if($this->db->trans_status() === FALSE){
   $this->db->trans_rollback();
}else{
   $this->db->trans_complete();
}
 2
Author: Kahlil Vanz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-21 03:39:49