So i'm trying to run an query by using a transaction but it's not working somehow i did check all the posts but no fixes seems to be working ! whenever i remove the transaction the insert query works just fine.
Here's the controller :
public function addEmployee(){
$field = array(
'NomClient'=>$this->input->post('fullName'),
'TelClient'=>$this->input->post('tel'),
'WilayaClient'=>$this->input->post('wilaya'),
'CommuneClient'=>$this->input->post('commune'),
'AdresseClient'=>$this->input->post('adresse'),
'StatusID'=>$this->input->post('statusCommande'),
'TelevendeuseID'=>$this->input->post('televendeuse')
);
$result= $this->m->addEmployee($field);
$msg['success'] = false;
$msg['type'] = 'add';
if($result){
$msg['success'] = true;
}
echo json_encode($msg);
}
My model :
public function addEmployee($field){
$this->db->trans_start();
return $this->db->insert('Clients',$field);
$this->db->trans_complete();
}
Please note that when i switch the model to :
public function addEmployee($field){
return $this->db->insert('Clients',$field);
}
The record gets inserted successfully ! Which means that something is wrong with the transaction. I'm currently using one query to test if it's working so i can use multiples onces after that. Note that the tables are InnoDB tables so the problem isn't with the table type. Please help me out !
When you call return it will end the function, so when it hits
return $this->db->insert('Clients',$field);
it will not get to
$this->db->trans_complete();
so perhaps...
$this->db->trans_start();
$return = $this->db->insert('Clients',$field);
$this->db->trans_complete();
return $return;
Related
I have read up on some stuff about transactions in Codeigniter. I have implemented them in my code and was wondering if someone could take a look and see if I am going in the right direction? So far I have not encountered any database issues but I want to make sure I have implemented transactions correctly.
In my code, I create the user details first and get the ID, then I insert that ID into the user accounts table.
Controller
if($this->form_validation->run()==false){
$this->index();
}else{
$password = md5($password);
$package = array(
'first_name'=>$first_name,
'last_name'=>$last_name,
'email'=>$email,
'client_id'=>$client_id,
'date_of_birth'=>$date_of_birth,
'phone_number'=>$phone_number,
'address'=>$address,
'country'=>$country,
'created_on'=>$this->get_date(),
'updated_on'=>$this->get_date()
);
if($this->AccountModel->user_account_exists($email)){
$this->session->set_flashdata('Error',"Account already exists");
redirect('/Register');
}else{
$this->db->trans_start();
$id = $this->AccountModel->create_person($package);
$error = $this->db->error();
$this->db->trans_complete();
$expiration_date = date('Y-m-d', strtotime($this->get_date() . "+1 month") );
if($this->db->trans_status()===false){
$this->index();
}else{
$account = array(
'username'=>$email,
'password'=>$password,
'user_type'=>'user',
'person_id'=>$id,
'is_active'=>true,
'created_on'=>$this->get_date(),
'updated_on'=>$this->get_date(),
'expires_on'=>$expiration_date,
'status'=>'active'
);
$this->db->trans_start();
$id = $this->AccountModel->create_user_account($account);
$error = $this->db->error();
$this->db->trans_complete();
if($this->db->trans_status()===false){
$this->index();
}else{
$this->session->set_flashdata('Success','Account has been created');
redirect('/Login');
}
}
}
if($error!=''){
$this->session->set_flashdata('Error',$error["message"]);
redirect('/Register');
}
}
Model
public function create_user_account($input){
$this->db->insert('user_accounts',$input);
return $this->db->insert_id();
}
public function create_person($input){
$this->db->insert('person',$input);
return $this->db->insert_id();
}
Hope someone can help me with this
The reason for transactions is to perform multiple db query operations and if any operations fail undo any that have already taken place.
You are only performing one operation within your transaction block so transactions are pointless. Other than that, you've got the idea.
In your case where you are only using db->insert() you can easily check the results and respond accordingly. db->insert() returns either true or false. If the return is false, get the error and set it into flashdata. Otherwise, go on with your work.
As #Topjka say, transactions should be in the model code.
Here's a sample model
class Some_model extends CI_Model
{
public function save_stuff($data)
{
//let's assume $data has values for two different tables
$newInfo = $data['newStuff'];
$updateInfo = $data['oldStuff'];
$this->db->trans_start();
$this->db->insert('other_table', $newInfo);
$this->db->update('one_table', $updateInfo);
$this->db->trans_complete();
if($this->db->trans_status() === FALSE)
{
$this->set_flash_error();
return FALSE;
}
return TRUE; //everything worked
}
public function set_flash_error()
{
$error = $this->db->error();
$this->session->set_flashdata('Error', $error["message"]);
}
}
Transactions are justified above because we do two db ops and if the either fails we don't want any changes to the db made.
Using the model/method in the controller
if($this->some_model->save_stuff($the_stuff) === FALSE)
{
redirect('/wherever');
}
//All OK, proceed
//do other controller things
I have an update function in my Model which I call from My controller as
if($_POST)
{
$this->User_model->update('user_about',$_POST,$this->session->userdata['id']);
}
takes three parameters, table name, post data and user id. The function is defined in the Model as
public function update($table,$data,$id)
{
$row=$this->db->select('*')->from($table)->WHERE('user_id',$id)->row();
if($row)
{
$this->db->WHERE('user_id',$id)->UPDATE($table,$data);
}
else
{
$data['user_id']=$id;
$this->db->insert($table,$data);
}
}
What I am doing here is checking if the record of particular user doesn't exist it should insert, otherwise update. Works like a charm
Question
Is there a way to skip the IF condition block?. Is there any provision in query builder which performs the check itself?
Here is a custom generic insert and update on duplicate function that I always used in my programming.
public function updateOnDuplicate($table, $data )
{
if (empty($table) || empty($data)) return false;
$duplicate_data = array();
foreach($data AS $key => $value) {
$duplicate_data[] = sprintf("%s='%s'", $key, $value);
}
$sql = sprintf("%s ON DUPLICATE KEY UPDATE %s", $this->db->insert_string($table, $data), implode(',', $duplicate_data));
$this->db->query($sql);
return $this->db->insert_id();
}
You can use the above function in the model and call it in the controller. The function will update the value if the duplicate occurs. Check out following blog post if you need detail explanation A Generic CodeIgniter Function for both Update and Insert.
How to insert same data into database after update in ORM?
For example i have function save() and inside this function i have update and it's working, but i don't know how to make insert with old update data. I mean it should make something like history in database. I only hope you can understand what i mean. Thanks for help.
public function save(Validation $validation = NULL)
{
if ($this->loaded()) {
// UPDATE TRIGGER
DB::update($this->_table_name)
->set(array('ud_status' => 'D'))
->where('ud_status', '=', 'A')
->where('ud_uId', '=', $this->ud_uId)
->execute($this->_db);
return false;
} else {
// INSERT TRIGGER
return parent::save($validation);
}
}
$query = DB::insert('users', array('username', 'password'))->values(array('fred', 'p#5sW0Rd'));
https://kohanaframework.org/3.3/guide/database/query/builder#insert
I have a problem when I want to call more than one stored procesure in the controller. just only one stored procedure that execute.
This query stored procedure in the model :
function getKategori(){
$query = $this->db->query("call KategoriSelectPro('id_kategori','kategori')");
return $query->result();
}
function getEditSubKategori($id_subkategori){
$query = $this->db->query("call SubKategoriEditSelectPro(?,'id_kategori','kategori','sub_kategori')", $id_subkategori);
return $query->row_array();
}
and this code in controller:
function subkategoriedit($id_subkategori = ''){
$data['kategori'] = $this->madmin->getKategori();
$data['editsubkategori'] = $this->madmin->getEditSubKategori($id_subkategori);
}
The problem is only one function of the model can be called in the controller. example:
$data['kategori'] = $this->madmin->getKategori(); (SUCCESS)
$data['editsubkategori'] = $this->madmin->getEditSubKategori($id_subkategori); (NOT RUN)
The error message is :
Commands out of sync; you can't run this command now
so if reversed.
help me, how to call multiple store procedure in CodeIgniter?
I had the same problem a couple of moments earlier, searched for it on stackoverflow, found the answer and forgot to rate the answer .. anyhow
add the following function in file
system > database > drivers > mysqli > mysqli_driver.php
function next_result()
{
if (is_object($this->conn_id))
{
return mysqli_next_result($this->conn_id);
}
}
and then add the following command after every calling query you perform.
$this->db->next_result();
it worked like a charm for me ..
in your model change return $query->row_array(); to return $query->result_array();
function getKategori(){
$query = $this->db->query("call KategoriSelectPro('id_kategori','kategori')");
return $query->result();
}
function getEditSubKategori($id_subkategori){
$query = $this->db->query("call SubKategoriEditSelectPro(?,'id_kategori','kategori','sub_kategori')", $id_subkategori);
return $query->result_array();
}
Good Evening,
I got a problem with the last insert id function with active record codeigniter, it works fine in mysql. But when i try it on SQL Server, the result always return false. Please kindly take a look on my code:
function transactions_start($data) {
$this->db->insert($this->table, $data);
$id = $this->db->insert_id();
$q = $this->db->affected_rows();
if ($q > 0) {
return $id;
} else {
return FALSE;
}
}
this is the result of $this->db->last_query()
select ##IDENTITY as id
the var_dump() result always returning bool(false).
I'm developing this apps using MySQL and SQL Server, so i need to keep using the active record from codeigniter.
Any help would be great, thanks in advance!
The insert_id() function returns the id of last inserted row so you just check whether it is greater than 0 or not. Use it like
function transactions_start($data) {
$this->db->insert($this->table, $data);
$id = $this->db->insert_id();
if ($id > 0) {
return $id;
} else {
return FALSE;
}
}
Reference : https://ellislab.com/codeigniter/user-guide/database/helpers.html