2013-06-18 22 views
5

Ben CodeIgniter veritabanında (aynı tablo) bazı satırları eklemek için küçük bir yöntem çalıştırıyorum. Hangi ekleme işleminin bir işlemde başarısız olduğunu görmek istiyorum (bir dizi başlık döndürerek). Benim kodudur:Codeigniter, işlemde hata izleme

$failure = array(); //the array where we store what failed 
$this->db->trans_start(); 
foreach ($data as $ressourceCsv){ //data is an array of arrays to feed the database 
    $this->ajout_ressource($ressourceCsv); //method to insert (basically, just an insert with active record) 
    if (($this->db->_error_message())!=null) { 
      $failure[] = $ressourceCsv['title']; 
    } 
} 
$this->db->trans_complete(); 
return $failure; 

gerçektir ki ben bunu bir işlem yapmazsanız (hayır $ this-> _... db-> trans), bu mükemmel çalışıyor ve birkaç içeren bir dizi var başlıklar. Ancak işlemle, dizi ilk hatadan beri her başlık içerir. Ekleme işleminden başlayarak, işlemin geri alınmasına neden olan başlığı almanın bir yolu var mı?

Ben de birlikte çalıştık:

$failure = array(); //the array where we store what failed 
$this->db->trans_start(); 
foreach ($data as $ressourceCsv){ //data is an array of arrays to feed the database 

    if (!$this->ajout_ressource($ressourceCsv)) { //active record insertion return true 
      $failure[] = $ressourceCsv['title']; // if successful 
    } 
} 
$this->db->trans_complete(); 
return $failure; 

cevap

1

bir hata, bir işlem içinde gerçekleştiği takdirde size artık DB mods önce geri alma yapılabilir gerektiğine inanıyoruz. Gördüğünüz davranışı açıklar. İlk hatanın ardından, işlem "iptal edildi" ve döngüsüne devam edersiniz, böylece her SQL komutu da başarısız olur. kontrol etmek $this->db->trans_status() === FALSE kullanın: bir "geri alma" bir hata (. bu bir yazım hatası değildi) Ayrıca

olmadığını BTW yok "işlemek" gibi görünüyor

db=# select * from test1; 
id | foo | bar 
----+-----+----- 
(0 rows) 

db=# begin; 
BEGIN 
db=# insert into test1 (foo, bar) values (1, 'One'); 
INSERT 0 1 
db=# insert into test1 (foo, bar) values (Oops); 
ERROR: column "oops" does not exist 
LINE 1: insert into test1 (foo, bar) values (Oops); 
              ^
db=# insert into test1 (foo, bar) values (2, 'Two'); 
ERROR: current transaction is aborted, commands ignored until end of transaction block 
db=# select * from test1; 
ERROR: current transaction is aborted, commands ignored until end of transaction block 
db=# commit; 
ROLLBACK 
ace_db=# select * from test1; 
id | foo | bar 
----+-----+----- 
(0 rows) 

db=# 

Not: aşağıdaki gibi gösterilebilir işlem sırasında bir hata için.

Güncelleme: ekler başkaları tarafından görülmediğinden böylece hazır olana kadar burada bir işlemde bunu yapmak için bazı (denenmemiş) kod:

$failure = array(); //the array where we store what failed 
$done = false; 
do { 
    $this->db->trans_begin(); 
    foreach ($data as $key => $ressourceCsv){ //data is an array of arrays to feed the database 
     $this->ajout_ressource($ressourceCsv); //method to insert (basically, just an insert with active record) 
     if ($this->db->trans_status() === false) { // an insert failed 
      $failure[] = $ressourceCsv['title']; // save the failed title 
      unset($data[$key]);     // remove failed insert from data set 
      $this->db->trans_rollback();   // rollback the transaction 
      break;         // retry the insertion 
     } 
    } 
    $done = true;         // completed without failure 
} while (count($data) and ! $done);    // keep going until no data or success 

/* 
* Two options (uncomment one): 
* 1. Commit the successful inserts even if there were failures. 

$this->db->trans_commit(); 

* 2. Commit the successful inserts only if no failures. 

if (count($failure)) { 
    $this->db->trans_rollback(); 
} else { 
    $this->db->trans_commit(); 
} 
*/ 

return $failure; 
+0

Ok, ben, değil alırsanız İşlemlerin çok yapısı, istediğim gibi ilerlememe izin vermiyor. Ayrıca $ this-> db-> trans_status() === FALSE değerini kullanamıyorum çünkü aslında işlem satırlarını if deyiminde (her zaman bir işlem kullanmıyorum) sardım. Benim sorunu çözmek için, sonunda bir rollback ve $ başarısızlık dizisi boş değilse ben sonunda onları silmek için başarılı ekleme id idrarını saklıyorum – Dargor

+0

Eğer ** olursa olsun tüm ekler aynı anda herhangi bir başarısızlıktan sonra bunu yapabilirsin, ama eğer niyetiniz, eğer kimsenin başarısız olması durumunda bu eklerden herhangi birini görmeyecekse, o zaman bu şekilde başaramazsınız. "Kabul edilen" adlı bir boolean sütunu olabilir ve yalnızca tüm ekler bittikten ve hiçbiri başarısız olduktan sonra TRUE ayarlayabilir ve diğer sorgularınıza "WHERE accepted = TRUE" ifadesini ekleyebilirsiniz. – user9645

+0

İsterseniz, döngüyü bir işlemin içinde nasıl yapacağınızı göstermek için Güncelleştirmeyi ekledim. – user9645