简体   繁体   English

Codeigniter交易

[英]Codeigniter Transactions

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_start and trans_complete I'm calling other functions and those functions deals with database so they contains inserts and update and some deletes ... ex: 这工作正常,我trans_complete的问题是在trans_starttrans_complete我正在调用其他函数,这些函数处理数据库,因此它们包含插入和更新以及一些删除... ex:

$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_stat and trans_complete ) And if it returns an error test an do $this->db->trans_rollback 我想到的唯一解决方案是从这些函数返回错误,并在这些函数中添加( trans_stattrans_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);
    }

Using transactions means support databases to insert data safely. 使用transactions意味着支持数据库安全地插入数据。 So in Codeigniter we write every database related functions in the Model not in Controller. 所以在Codeigniter中,我们Model中编写每个与数据库相关的函数而不是在Controller中。 . And in your second code(which is not working)you have pointed model on there.( utils ). 在你的第二个代码(不工作)中你有指向模型。( utils )。 So simple I'm sure this will not work. 这么简单我敢肯定这不起作用。 Because its not a insert data with model and Controller parallel. 因为它不是与模型和Controller并行的插入数据。 Transaction should be coded in the Model( I will write in Model in my answer ). 交易应该在模型中编码( 我将在我的答案中写入模型 )。


Load this stuffs as well 加载这些东西

  1. Database Library 数据库库
  2. Model Class 模型类
  3. URL helper URL帮助器
  4. Session 会议

Assumptions 假设

In your code you have used $data and $test as array. 在您的代码中,您使用$data$test作为数组。 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 笔记

  1. By default Codeigniter runs all transactions in Strict Mode. 默认情况下,Codeigniter以严格模式运行所有事务。 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 . 如果禁用严格模式 ,则会独立处理每个组, 这意味着一个组的故障不会影响任何其他组

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. 我怀疑问题与CodeIgniter处理对象的方式有关。

If you go to the CI documentation under the section "Creating Libraries" at: 如果您转到“创建库”部分下的CI文档:
http://ellislab.com/codeigniter/user-guide/general/creating_libraries.html 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. 然后继续打开事务,然后通过utils库访问数据库函数。

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. 但是,一旦在库中使用$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_m to 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提供应用程序文件,或者将它们压缩并发送给您。


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格式

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

For single insert or update record you can use affected_rows function 对于单个插入或更新记录,您可以使用affected_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());
              }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM