I am calling multiple models in controllers and all models do database query.
i did something like this
public function InsertSale()
{
$this->db->trans_start(TRUE);
// all logic part and models calling which do insert/update/delete
$this->db->trans_complete();
}
Above code is not working even if something fails after some queries they dont rollback.
Having true in $this->db->trans_start(true); will put the transaction in to test mode which means that, regardless of what happens, the query will be rolled back.
If you wanted to see if the query would work you would use:
$this->db->trans_status();
Which will return either true/false depending on the outcome.
So that you have to follow like this
$this->db->trans_start(); # Starting Transaction
$this->db->trans_strict(FALSE);
$this->db->insert('table_name', $someDataArray); # Inserting data
# Updating data
$this->db->where('id', $id);
$this->db->update('table_name', $someDataArray);
$this->db->trans_complete();
This is work fine. Check this answer too
Related
We have an api function which check a condition on database with a select-query then if it was true we want just for one time insert some thing to database for example inserting to database that insertion done. Problem is when we call multiple times this api-function concurrently race condition happen, in another words assume we call this function 2 times, first request check the condition it's true then second request check that and it's true again so their do insert to database. But we want to when we check condition no other one can check it again until we do insertion.
We use php/Laravel and know about some ways like using insert into ... select or using some thing like replace into ... and so on.
$order = Order::find($orderId);
$logRefer = $order->user->logrefer;
if (!is_null($logRefer) && is_null($logRefer->user_turnover_id)) {
$userTurnover = new UserTurnover();
$userTurnover->user_id = $logRefer->referrer_id;
$userTurnover->order_id = $order->id;
$userTurnover->save();
$logRefer->order_id = $order->id;
$logRefer->user_turnover_id = $userTurnover->id;
$logRefer->save();
}
If logrefer not found set it and corresponding user-turnover just for one time. We expect to see just one user-turnover related to this order but after running it multiple time concurrently we see multiple user-turnover has inserted.
I usually take advantage of transaction when operations need to be sequential but i think that in your case the situation it's a bit complex due to the fact that also the condition need to be evaluated conditionally if the function it's running. So the idea that i can give you it's to have on the database a variable (another table) used as semaphore which allow or not to perform actions on the table (condition gived by the fact that you set or unset the value of the semaphore). I think as good programmer that semaphore are useful in a lot of cases of concurrential functions.
The database should have a unique key on columns expected to be unique, even if some mechanism in the code prevents duplicates.
Wrap connected queries into a transaction which will fail and roll back in a race event condition
try {
DB::transaction(function() {
$order = Order::find($orderId);
...
$logRefer->save();
});
} catch (\Illuminate\Database\QueryException $ex) {
Log::error(“failed to write to database”);
}
Below is the syntax from a Model using Codeigniter Framework. So i want to do this kind of query, i grouped many query inside another class like this, but i used this transaction outside the class like this.
$this->db->trans_begin();
$insert1 = $this->Actmain->tempPerwakilanToTransaksi($t_nib_kppa_temp['id_permohonan']);
$insert2 = $this->Actmain->transaksiPerwakilanToHistory($t_nib_kppa_temp['id_permohonan'],$arrData['id_history']);
if(!$insert1 || !$insert2) {
$this->db->trans_rollback();
return FALSE;
} else {
$this->db->trans_commit();
echo "Yatta desune"
}
I want to check if at least one query that didn't work successfully, it will rollback all the query. The problem is, it's always return true which came from query in variable $insert1 or $insert2. It's always echo Yatta Desune but the insert and update query didn't executed.
What is the proper way to used db transaction in Codeigniter 3 but bunch of query executed in different Model ?
I have a problem with laravel
I want to use a query result in my controller with a if clause to manage what i return to the view.
$res = Chaussures::where('id',$id);
if($res->name=='Adidas'){
return...
}
else {
return...
}
I tried this but it didn't work
You need to execute the query to get the result first. Then you can do whatever you need with the data.
$res=Chaussures::where('id',$id)->first();
Searching for models by ID is such a common task that Laravel has a method called find() to make it easier. This line does the same as the above.
$res=Chaussures::find($id);
as there are two possible way to implement transactions in codeigniter:
1.automatic
2.manual
I am getting an error like :Lock_wait_timeout in my codeigniter application.I don't have any wrong query in my code.But i found that i have wrote transaction code for automatic transaction similar to manual transaction.
as automatic transaction uses trans_start() ,on the other hand manual transaction uses trans_begin().
For manual transaction codeigniter uses the following syntax
$this->db->trans_begin();
insert query...
update query...
if($this->db->trans_status()===FALSE){
$this->db->trans_rollback();
}else{
$this->db->trans_commit();
}
But i have used automatic transaction in my code,and wrote it like the following(used if else statement like manual transaction):
$this->db->trans_start();
insert query...
update query...
$this->db->trans_complete();
if($this->db->trans_status()===FALSE){
$this->db->trans_rollback();
}else{
$this->db->trans_commit();
}
The function trans_complete() does almost exactly the same thing as your if/else statement as it makes a call to either trans_rollback() or trans_commit() as appropriate. Undoubtedly your second attempt at commit or rollback is greatly confusing your database. Just remove your if/else and all should be good.
In CodeIgniter, Are we also allowed to use "Active Record Class" like this?
<?php
$data_balance = array(
'balance' => $newbalance
);
$data_transaction = array(
'amount' => $amount,
'user' => $user
);
$this->db->trans_start();
// This is an "Insert" query for a table
$this->db->set('date', 'NOW()', FALSE);
$this->db->insert('financial_transactions', $data_transaction);
// This is an "Update" query for another table
$this->db->where('user_id', $user_id);
$this->db->update('financial_balances', $data_balance);
$this->db->trans_complete();
if ($this->db->trans_status() === FALSE){
// Do stuff if failed
}
?>
Note that i use $this->db-> for both queries, so i don't know if the success result of first one is actually cleared to check the second one?
Is this going to work? can i trust that this will make either both queries to success or neither of them (i don't want one to success and one to fail)
From documentation:
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.