web-dev-qa-db-ja.com

Codeigniterトランザクション

Codeigniterトランザクションを使用しています

$this->db->trans_start();
$this->db->query('AN SQL QUERY...');
$this->db->trans_complete();

これはうまく機能しますが、私が持っている問題はtrans_startおよびtrans_complete私は他の関数を呼び出しており、それらの関数はデータベースを処理するので、挿入と更新、およびいくつかの削除が含まれています。

$this->db->trans_start();
 $this->utils->insert_function($data);
 $this->utils->update_function2($test);
$this->db->trans_complete();

これらの関数が実行され、いくつかのエラーが発生した場合、CodeIgniterはロールバックを行いません。

そのような問題に対処する最良の方法は何ですか?

唯一の解決策は、これらの関数からエラーを返し、それらの関数内でadd(trans_statおよびtrans_complete)エラーテストが返された場合、do $this->db->trans_rollback

例:

    $this->db->trans_start();
     $result = $this->utils->insert_function($data);
     if($result === false){
       $this->db->trans_rollback();
     }
    $this->db->trans_complete();

これを行うより良い方法はありますか?

更新1:

要求されたように、私が呼び出している外部関数のサンプル:

   // 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);
    }
32
Tarek

transactionsを使用することは、データを安全に挿入するためのデータベースのサポートを意味します。そのため、Codeigniterでは、すべてのControllerにないModelのデータベース関連関数を記述します。そして、2番目のコード(動作していない)でモデルをポイントしました(utils)。とても簡単なので、これはうまくいかないでしょう。その理由は、モデルとコントローラーが並行する挿入データではないからです。トランザクションは、モデルにコーディングする必要があります(回答にモデルを記述します)。


これもロードする

  1. データベースライブラリ
  2. モデルクラス
  3. URLヘルパー
  4. セッション

仮定

コードでは、$data$testを配列として使用しています。したがって、データを挿入および更新するための2つの配列があると想定しています。


データセット

$data = array(
   'title' => 'My title' ,
   'name' => 'My Name' ,
   'date' => 'My date'
);

$id = 007;
$test = array(
   'title' => $title,
   'name' => $name,
   'date' => $date
);

あなたのコード

$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;
}

  1. デフォルトでは、Codeigniterはすべてのトランザクションを厳格モードで実行します。 strictモードがenabledの場合、トランザクションの複数のグループを実行している場合、1つのグループが失敗すると、すべてのグループがロールバックされます。モードはdisabled、各グループは独立して扱われる1つのグループの障害が他に影響を与える
36
Abdulla Nilam

私が試したのはもう少しトリックでしたが、うまくいきました。

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

この手順を試してください。それは本当に私のために働く:)

$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();
}
3
Kahlil Vanz

この問題は、CodeIgniterがオブジェクトを処理する方法に関係していると思われます。

次の「ライブラリの作成」セクションの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');

メインコントローラで、自動ロードを使用するか、クラスを明示的にロードすることにより、データベースクラスをロード/インスタンス化しました。

次に、トランザクションを開いてから、utilsライブラリを介してデータベース関数にアクセスします。

ただし、$this-dbライブラリでは、トランザクションに関連付けられているものではなく、実際にデータベースインスタンスの別のコピーにアクセスしています。

同じインスタンスにアクセスするには、get_instance()関数を使用する必要があります。

これで問題は解決するはずです。機能をさまざまなモジュールに分離する独自のコーディングスタイルが優れています。この追加の詳細を理解するだけです。

ロールバックが期待どおりに機能することを確認してください。

コードの本質は、次のコントローラーで構成されています。

$this->db->trans_start();
$this->User_profile_m->create_new_user_profile();
$this->User_profile_m->create_new_user();
$this->db->trans_complete(); 

シンプルなモデル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);  
}

基本的に、デモンストレーションは2つの挿入(2つのテーブルに1つずつ)を試みます。一方の挿入が失敗すると、もう一方はロールバックされます。

これをCodeIgniter 2.1.3で作成し、GitHubを介してアプリケーションファイルを利用可能にするか、Zipで圧縮して送信できます。

3
Marc Audet


注:手動トランザクションを実行するときは、$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 ();

MySqlを使用する場合に認証し、InnoDb形式で使用する

3
Diego

単一の挿入または更新レコードの場合、impacted_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());
              }
0
bdalina