Transactions Codeigniter

j'utilise des transactions Codeigniter

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

Cela fonctionne bien , le problème que j'ai c'est qu'à l'intérieur de l' trans_start et trans_complete j'appelle d'autres fonctions et ces fonctions traitent avec la base de données de sorte qu'elles contiennent des inserts et des mises à jour et quelques suppressions ... ex:

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

si ces fonctions sont exécutées et que certaines erreurs se produisent, CodeIgniter ne fera pas de rollback.

Quelle est la meilleure façon de traiter cette question?

le seul la solution, je pense, est de renvoyer un message d'erreur à partir de ces fonctions et à l'intérieur de la fonction ajouter (trans_stat et trans_complete) et si elle renvoie un test d'erreur Un 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();

Est-il une meilleure manière de faire ceci?

mise à jour 1:

Comme l'a demandé à un échantillon de la fonction externe je vais appeler :

   // 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);
    }
29
demandé sur Abdulla Nilam 2013-03-05 17:19:17

5 réponses

en utilisant transactions signifie bases de données de soutien pour insérer des données en toute sécurité. Donc dans Codeigniter nous écrivons chaque fonctions relatives à la base de données dans le Modèle pas dans le contrôleur.. Et dans ton deuxième code(qui ne fonctionne pas)vous l'avez fait modèle.(utils). Si simple que je suis sûr que ça ne marchera pas. Parce que ce n'est pas un insert données avec modèle et contrôleur parallèle. La Transaction doit être codée dans le modèle(je vais écrire à Modèle dans ma réponse).


Charger ce fourre ainsi

  1. Bibliothèque De Base De Données
  2. Modèle De Classe
  3. helper URL
  4. Session

suppositions

dans votre code vous avez utilisé $data et $test en tant que tableau. Donc je suppose qu'il y a deux tableaux pour insérer et mettre à jour données.


vos ensembles de données

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

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

Votre Code

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

Notes

  1. par défaut Codeigniter exécute toutes les transactions en mode Strict. Lorsque le mode strict est activé, si vous exécutez plusieurs groupes de transactions, si un groupe n'arrive pas tous les groupes seront annulées. Si le mode strict est désactivé, chaque groupe est traités indépendamment,sens d'une défaillance d'un groupe n'affecte pas les tout les autres.
28
répondu Abdulla Nilam 2016-08-25 09:00:59

ce que j'ai essayé était plus un tour, mais ça a fonctionné pour moi.

$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
répondu Heshan Rajapaksha 2016-08-08 23:22:39

je soupçonne que le problème est lié à la façon dont CodeIgniter manipule les objets.

si vous allez à la documentation CI sous la rubrique "Création de bibliothèques" at:

http://ellislab.com/codeigniter/user-guide/general/creating_libraries.html

et de regarder la section relative à:

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

dans votre controller principal, vous avez chargé/instancié la classe de base de données en utilisant auto load ou en chargeant explicitement classe.

vous ouvrez alors la transaction, puis vous accédez à votre base de données fonctions à travers votre bibliothèque utils.

cependant, si vous utilisez $this-db dans votre bibliothèque, vous accédez en fait à une autre copie de l'instance de la base de données, Pas celle qui est associée à votre transaction.

pour accéder À la même instance, vous devez utiliser le get_instance() fonction.

je pense que ça devrait régler votre problème. L'original de votre codage style pour séparer les fonctions dans divers modules est excellent. Vous devez simplement comprendre ce détail supplémentaire.

veuillez essayer de confirmer que le roll back fonctionne comme prévu.

Les entrailles du code se compose du contrôleur suivant:

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

et un modèle simple user_profile_m pour faire face à la persistance des données:

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

Essentiellement, la manifestation essaie de faire deux inserts (un dans chacune des deux tables). Si une insertion échoue, la autres est annulée.

j'ai construit ceci dans CodeIgniter 2.1.3 et je peux rendre les fichiers d'application disponibles via GitHub ou les zip et les envoyer à vous.

3
répondu Marc Audet 2014-03-27 01:59:42



Remarque: assurez-vous d'utiliser $this->db->trans_begin() lors de l'exécution de mouvements manuels, pas $this->db->trans_start().

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

certifier au cas où utiliser MySql, utiliser dans le Format InnoDb

2
répondu Diego 2014-01-30 15:07:25

Essayez cette procédure. Il fonctionne vraiment bien pour moi :)

$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
répondu Kahlil Vanz 2014-07-21 03:39:49