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);
}
transactions
を使用することは、データを安全に挿入するためのデータベースのサポートを意味します。そのため、Codeigniterでは、すべてのControllerにないModelのデータベース関連関数を記述します。そして、2番目のコード(動作していない)でモデルをポイントしました(utils
)。とても簡単なので、これはうまくいかないでしょう。その理由は、モデルとコントローラーが並行する挿入データではないからです。トランザクションは、モデルにコーディングする必要があります(回答にモデルを記述します)。
これもロードする
仮定
コードでは、$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;
}
注
私が試したのはもう少しトリックでしたが、うまくいきました。
$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();
}
この手順を試してください。それは本当に私のために働く:)
$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();
}
この問題は、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で圧縮して送信できます。
注:手動トランザクションを実行するときは、$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形式で使用する
単一の挿入または更新レコードの場合、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());
}