Сделки Codeigniter

Я использую транзакции Codeigniter

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

Это прекрасно работает, проблема заключается в том, что внутри trans_start и trans_complete я trans_complete другие функции, и эти функции работают с базой данных, поэтому они содержат вставки и обновление, а некоторые удаляются … ex:

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

Теперь, если эти функции выполняются и возникают некоторые ошибки, CodeIgniter не будет откатываться.

Каков наилучший способ решения этой проблемы?

Единственное решение, которое я имею в виду, – это вернуть ошибку из этих функций и внутри этой функции add (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 ();

Есть ли лучший способ сделать это?

Обновление 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 мы записываем каждую связанную с базой данных функцию в Model, а не в Controller. , И в вашем втором коде (который не работает) вы указали модель там. ( utils ). Так просто, я уверен, что это не сработает. Потому что его не вставляют данные с моделью и контроллером параллельно. Транзакция должна быть закодирована в модели ( я напишу в модели в своем ответе ).


Загрузите эти материалы также

  1. Библиотека базы данных
  2. Модельный класс
  3. URL-адрес помощника
  4. сессия

Предположения

В вашем коде вы использовали $data и $test as array. Поэтому я предполагаю, что есть два массива для вставки и обновления данных.


Ваши наборы данных

 $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 выполняет все транзакции в строгом режиме. Если включен режим строгого режима, если вы используете несколько групп транзакций, если одна группа не работает, все группы будут отброшены назад. Если строгий режим отключен , каждая группа рассматривается независимо , что означает , что отказ одной группы не повлияет на других .

Я подозреваю, что проблема связана с тем, как 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); } 

По сути, демонстрация пытается сделать две вставки (по одной в каждой из двух таблиц). Если одна вставка выходит из строя, другая откатывается назад.

Я построил это в CodeIgniter 2.1.3, и я могу сделать файлы приложений доступными через GitHub или закрепить их и отправить их вам.

То, что я пробовал, было скорее хитростью, но это сработало для меня.

 $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_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

Попробуйте эту процедуру. Это действительно работает для меня 🙂

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