tutorial transaction transacciones trans_start trans_begin igniter code php mysql codeigniter transactions codeigniter-3

php - transaction - this-> db-> trans_begin()



Transacciones de Codeigniter (5)

Usar transactions significa bases de datos de soporte para insertar datos de manera segura. Entonces, en Codeigniter escribimos todas las funciones relacionadas con la base de datos en el Modelo que no está en el Controlador. . Y en su segundo código (que no funciona), ha apuntado el modelo allí ( utils ). Tan simple que estoy seguro de que esto no funcionará. Porque no es una inserción de datos con modelo y controlador paralelo. La transacción debe estar codificada en el Modelo ( escribiré en el Modelo en mi respuesta ).

Carga esto también

  1. Biblioteca de base
  2. Clase de modelo
  3. Ayudante de URL
  4. Sesión

Suposiciones

En su código, ha usado $data y $test como matriz. Entonces supongo que hay dos arreglos 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 );

Tu codigo

$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. De forma predeterminada, Codeigniter ejecuta todas las transacciones en el 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á deshabilitado , cada grupo se trata de manera independiente , lo que significa que una falla de un grupo no afectará a ninguna otra .

Estoy usando transacciones de 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 la trans_start y trans_complete estoy llamando a otras funciones y esas funciones se ocupa de la base de datos por lo que contienen inserciones y actualizaciones y algunas elimina ... 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 se producen algunos errores, CodeIgniter no realizará una reversión.

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

La única solución, tengo en mente, es devolver un error de esas funciones y dentro de esas funciones agregar ( trans_stat y trans_complete ) Y si devuelve una prueba de error y 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?

Actualización 1:

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


Lo que probé 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(); }


Prueba este procedimiento. Realmente me funciona :)

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


Sospecho que el problema tiene que ver con cómo CodeIgniter maneja los objetos.

Si va a la documentación de CI en 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 la base de datos usando la carga automática o cargando explícitamente la clase.

A continuación, continúa y abre la transacción, y luego accede a las funciones de su base de datos a través de su biblioteca de utilidades.

Sin embargo, una vez que usa $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 arreglar tu problema. Su estilo de codificación original para separar la función en varios módulos es excelente. Simplemente necesita comprender este detalle adicional.

Intente y confirme que la reversión funciona como esperaba.

Las agallas 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 los 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); }

Básicamente, la demostración intenta hacer dos inserciones (una en cada una de las dos tablas). Si una inserción falla, la otra se retrotrae.

Lo construí en CodeIgniter 2.1.3 y puedo hacer que los archivos de la aplicación estén disponibles a través de GitHub o comprimirlos y enviártelos.



Nota: asegúrese de usar $this->db->trans_begin() al ejecutar 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 usar MySql, usar en formato InnoDb