Codeigniter Transactions
What I tried was more of a trick, but it worked for me.
$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();
}
I suspect the problem has to do with how CodeIgniter is handling objects.
If you go to the CI documentation under the section "Creating Libraries" at:
http://ellislab.com/codeigniter/user-guide/general/creating_libraries.html
and look at the section related to:
$CI =& get_instance();
$CI->load->helper('url');
$CI->load->library('session');
$CI->config->item('base_url');
In your main controller, you have loaded/instantiated the database class either using auto load or explicitly loading the class.
You then go ahead and open the transaction, and then, you access your database functions through your utils library.
However, once you use $this-db
in your library, you are actually accessing another copy of the database instance, NOT the one that is associated with your transaction.
To access the same instance, you need to use the get_instance() function.
I think that should fix your problem. Your original coding style to separate function into various modules is excellent. You simply need to understand this additional detail.
Please try and confirm that the roll back works as you expect.
The guts of the code consists of the following controller:
$this->db->trans_start();
$this->User_profile_m->create_new_user_profile();
$this->User_profile_m->create_new_user();
$this->db->trans_complete();
and a simple model user_profile_m
to deal with data persistence:
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);
}
Essentially, the demonstration tries to do two inserts (one in each of two tables). If one insert fails, the other is rolled back.
I built this in CodeIgniter 2.1.3 and I can make the application files available through GitHub or zip them up and send them to you.
Using
transactions
means support databases to insert data safely. So in Codeigniter we write every database related functions in the Model not in Controller.. And in your second code(which is not working)you have pointed model on there.(utils
). So simple I'm sure this will not work. Because its not a insert data with model and Controller parallel. Transaction should be coded in the Model(I will write in Model in my answer).
Load this stuffs as well
- Database Library
- Model Class
- URL helper
- Session
Assumptions
In your code you have used $data
and $test
as array. So i assume there is two array for inserting and updating data.
Your data sets
$data = array(
'title' => 'My title' ,
'name' => 'My Name' ,
'date' => 'My date'
);
$id = 007;
$test = array(
'title' => $title,
'name' => $name,
'date' => $date
);
Your 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
- By default Codeigniter runs all transactions in Strict Mode. When strict mode is enabled, if you are running multiple groups of transactions, if one group fails all groups will be rolled back. If strict mode is disabled, each group is treated independently, meaning a failure of one group will not affect any others.