Подтвердить что ты не робот

Сделки Codeigniter

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

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

Это хорошо работает, проблема заключается в том, что внутри trans_start и 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

например:       $ 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);
    }
4b9b3361

Ответ 1

Использование transactions означает базы данных поддержки для безопасного хранения данных. Поэтому в Codeigniter мы пишем каждую связанную с базой данных функцию в модели не в контроллере.. И в вашем втором коде (который не работает) вы указали модель там. (utils). Так просто, я уверен, что это не сработает. Потому что его не вставляют данные с моделью и контроллером параллельно. Транзакция должна быть закодирована в модели ( Я напишу в модели в своем ответе).


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

  • Библиотека базы данных
  • Класс модели
  • URL-адрес помощника
  • Session

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

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


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

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

Примечания

  • По умолчанию Codeigniter запускает все транзакции в Strict Mode. когда режим включен, если вы используете несколько групп транзакций, если одна группа не работает, все группы будут отброшены назад. Если строгий режим отключен, каждая группа обращается независимо, означает, что отказ одной группы не повлияет любые другие.

Ответ 2

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

Ответ 3

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

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

Ответ 4


Примечание. Обязательно используйте $this->db->trans_begin() при выполнении ручных транзакций, NOT $this->db->trans_start().

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

Сертифицировать в случае использования MySql, использовать в формате InnoDb

Ответ 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();
}