php Codeigniter 交易
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15224826/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Codeigniter Transactions
提问by Tarek
I'm using Codeigniter transactions
我正在使用 Codeigniter 交易
$this->db->trans_start();
$this->db->query('AN SQL QUERY...');
$this->db->trans_complete();
This works fine , the problem I have is that inside the trans_startand trans_completeI'm calling other functions and those functions deals with database so they contains inserts and update and some deletes ... ex:
这工作得很好,我有问题是内部的trans_start和trans_complete我打电话等功能,并与数据库中的那些功能的交易,使他们包含插入和更新以及一些删除...例如:
$this->db->trans_start();
$this->utils->insert_function($data);
$this->utils->update_function2($test);
$this->db->trans_complete();
Now if those functions are executed and some errors occur CodeIgniter won't do a rollback.
现在,如果这些函数被执行并且发生了一些错误,CodeIgniter 将不会进行回滚。
What is the best way to deal with such issue?
处理此类问题的最佳方法是什么?
The only solution, I have in mind, is to return an error from those functions and inside those function add (trans_statand trans_complete) And if it returns an error test an do $this->db->trans_rollback
我想到的唯一解决方案是从这些函数中返回一个错误,并在这些函数中添加(trans_stat和trans_complete)如果它返回一个错误测试,则执行$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();
Is there a better way of doing this?
有没有更好的方法来做到这一点?
Update 1:
更新 1:
As requested a sample of the external function i'm calling :
根据要求,我正在调用外部函数的示例:
// 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);
}
回答by Abdulla Nilam
Using
transactionsmeans support databases to insert data safely. So in Codeigniter we write every database related functions in the Modelnot 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).
使用
transactions手段支持数据库安全插入数据。所以在 Codeigniter 中,我们在Model 中而不是在 Controller 中编写每个数据库相关的函数。. 在您的第二个代码(不起作用)中,您在那里指出了模型。(utils)。如此简单,我确定这行不通。因为它不是模型和控制器并行的插入数据。交易应该在模型中编码(我会在我的回答中写在模型中)。
Load this stuffs as well
也加载这些东西
- Database Library
- Model Class
- URL helper
- Session
- 数据库库
- 模型类
- 网址助手
- 会议
Assumptions
假设
In your code you have used $dataand $testas array. So i assume there is two array for inserting and updating data.
在您的代码中,您使用$data和$test作为数组。所以我假设有两个数组用于插入和更新数据。
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.
- 默认情况下,Codeigniter 以严格模式运行所有事务。当 被严格模式启用,如果你正在运行的交易多组,如果一组发生故障,所有组将被回滚。如果禁用严格模式,则每个组都被独立处理,这意味着一个组的失败不会影响任何其他组。
回答by Heshan Rajapaksha
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();
}
回答by Marc Audet
I suspect the problem has to do with how CodeIgniter is handling objects.
我怀疑这个问题与 CodeIgniter 如何处理对象有关。
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 文档:
http: //ellislab.com/codeigniter/user-guide/general/creating_libraries.html
并查看与以下内容相关的部分:
$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.
然后继续打开事务,然后通过 utils 库访问数据库函数。
However, once you use $this-dbin your library, you are actually accessing another copy of the database instance, NOT the one that is associated with your transaction.
但是,一旦$this-db在您的库中使用,您实际上是在访问数据库实例的另一个副本,而不是与您的事务相关联的副本。
To access the same instance, you need to use the get_instance() function.
要访问同一个实例,您需要使用 get_instance() 函数。
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_mto deal with data persistence:
以及user_profile_m处理数据持久性的简单模型:
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.
我在 CodeIgniter 2.1.3 中构建了它,我可以通过 GitHub 提供应用程序文件,或者将它们压缩并发送给您。
回答by Diego
Note: Make sure to use $this->db->trans_begin()when running manual transactions, NOT $this->db->trans_start().
注意:确保$this->db->trans_begin()在运行手动事务时使用,而不是$this->db->trans_start().
$this -> db -> trans_begin();
$this -> utils -> insert_function ( $data );
$this -> utils -> update_function2 ( $test );
$this -> db -> trans_complete ();
Certify in case use MySql, use in InnoDb Format
证明在使用MySql的情况下,使用InnoDb格式
回答by Kahlil Vanz
Try this procedure. It really work for me :)
试试这个程序。它真的对我有用:)
$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();
}
回答by bdalina
For single insert or update record you can use affected_rows function
对于单个插入或更新记录,您可以使用fluence_rows 函数
$this->db->insert('table_name', xss_clean($data));
//Check if there is a record affected
if($this->db->affected_rows() > 0)
{
return true;
}
else
{
// if not succeeded
// check your last query
die($this->db->last_query());
}

