2013-02-27 30 views
54

Eloquent ORM khá tốt, mặc dù tôi tự hỏi liệu có cách nào dễ dàng để thiết lập các giao dịch MySQL bằng cách sử dụng innoDB cùng kiểu với PDO hay không, hoặc nếu tôi phải mở rộng ORM để thực hiện điều này khả thi?Giao dịch ORM Eloquent ORM

Trả lời

110

Bạn có thể làm điều này:

DB::transaction(function() { 
     // 
}); 

Tất cả mọi thứ bên trong đóng cửa thực hiện trong một giao dịch. Nếu một ngoại lệ xảy ra, nó sẽ tự động quay trở lại.

+1

Bên trong việc đóng cửa tôi có thể gọi các truy vấn trong một lớp học? Nó sẽ hoạt động? –

+0

Đáng buồn là nó không hoạt động đối với tôi nếu tôi đang tạo ra các thể hiện của các mô hình khác nhau đang lưu trữ bản ghi theo các phương pháp liên quan của riêng họ. – Volatil3

+0

Nếu tôi có ngoại lệ bên trong giao dịch của mình (để tạo thông báo lỗi, v.v), tôi có cần phải phát hành lại ngoại lệ để xảy ra việc khôi phục không? – alexw

64

Nếu bạn không thích chức năng ẩn danh:

try { 
    DB::connection()->pdo->beginTransaction(); 
    // database queries here 
    DB::connection()->pdo->commit(); 
} catch (\PDOException $e) { 
    // Woopsy 
    DB::connection()->pdo->rollBack(); 
} 

Cập nhật: Đối với laravel 4, đối tượng pdo không được công khai nữa vậy:

try { 
    DB::beginTransaction(); 
    // database queries here 
    DB::commit(); 
} catch (\PDOException $e) { 
    // Woopsy 
    DB::rollBack(); 
} 
+14

Bạn cũng có thể sử dụng các phương thức tắt «DB :: beginTransaction()' & 'DB :: commit()' & 'DB :: rollback()'. Đó sẽ là một chút sạch hơn. – Flori

+2

Vui lòng cập nhật để sử dụng đề xuất @Flori. Nó sạch hơn. Ngoài ra, di chuyển câu trả lời mới trở lên sẽ làm cho câu trả lời của bạn ít khó hiểu hơn. Tôi đã sử dụng phương pháp đầu tiên trước khi trở lại cho thứ hai. – frostymarvelous

18

Nếu bạn muốn sử dụng Eloquent, bạn cũng có thể sử dụng số này

Đây chỉ là mẫu mã từ dự án của tôi

 /* 
     * Saving Question 
     */ 
     $question = new Question; 
     $questionCategory = new QuestionCategory; 

     /* 
     * Insert new record for question 
     */ 
     $question->title = $title; 
     $question->user_id = Auth::user()->user_id; 
     $question->description = $description; 
     $question->time_post = date('Y-m-d H:i:s'); 

     if(Input::has('expiredtime')) 
      $question->expired_time = Input::get('expiredtime'); 

     $questionCategory->category_id = $category; 
     $questionCategory->time_added = date('Y-m-d H:i:s'); 

     DB::transaction(function() use ($question, $questionCategory) { 

      $question->save(); 

      /* 
      * insert new record for question category 
      */ 
      $questionCategory->question_id = $question->id; 
      $questionCategory->save(); 
     }); 
+0

Tôi đã thử một cái gì đó tương tự, nhưng không làm việc tôi chèn giao dịch và số tiền giao dịch là số thập phân (5, 2) và tôi chèn giá trị 999999.99999, sau đó tôi chạy eloquent thứ hai mà khấu trừ/tăng tín dụng người dùng (hợp lệ), tôi mong đợi nên ném một lỗi và rollback do các số thập phân giao dịch có định dạng sai nhưng giao dịch chỉ được chèn với giá trị trống và tín dụng người dùng cũng khấu trừ bất ngờ, bạn có biết tại sao không? – user259752

6

Đối với một số lý do nó là khá khó khăn để tìm thông tin này bất cứ nơi nào, vì vậy tôi quyết định đăng nó ở đây, như vấn đề của tôi, trong khi liên quan đến các giao dịch chứng hùng hồn và đang thay đổi một cách chính xác điều này.

Sau khi đọc THIS câu trả lời stackoverflow, tôi nhận ra các bảng cơ sở dữ liệu của tôi đã sử dụng MyISAM thay vì InnoDB.

Đối với giao dịch để làm việc trên Laravel (hoặc bất cứ nơi nào khác vì nó dường như), nó là cần thiết rằng bảng của bạn được thiết lập để sử dụng InnoDB

Tại sao?

Trích dẫn MySQL giao dịch và hoạt động nguyên tử docs (here):

MySQL Server (phiên bản 3.23-max và tất cả các phiên bản 4.0 trở lên) hỗ trợ các giao dịch với các công cụ lưu trữ giao dịch InnoDB và BDB. InnoDB cung cấp đầy đủ ACID tuân thủ. Xem Chương 14, Công cụ lưu trữ. Để biết thông tin về sự khác biệt của InnoDB từ SQL chuẩn đối với việc xử lý lỗi giao dịch, xem Phần 14.2.11, “Xử lý lỗi InnoDB”.

Các công cụ lưu trữ không chuyển đổi khác trong Máy chủ MySQL (như MyISAM) theo một mô hình khác nhau cho tính toàn vẹn dữ liệu được gọi là "hoạt động nguyên tử". Các hoạt động nguyên tử thường cung cấp tính toàn vẹn tương đương với hiệu suất cao hơn.

Vì máy chủ MySQL hỗ trợ cả hai mô hình, bạn có thể quyết định xem ứng dụng của bạn có được phục vụ tốt nhất bằng tốc độ hoạt động nguyên tử hoặc sử dụng các tính năng giao dịch hay không. Lựa chọn này có thể được thực hiện trên cơ sở mỗi bảng.

+0

Điều này đúng với DML và không phải lúc nào cũng đúng đối với DDL. –

10

Nếu bạn muốn tránh đóng cửa, và rất vui khi được sử dụng mặt tiền, sau đây giữ những điều tốt đẹp và sạch sẽ:

\DB::beginTransaction(); 

$user = \Auth::user(); 
$user->fill($request->all()); 
$user->push(); 

\DB::commit(); 

Nếu bất kỳ tuyên bố thất bại, cam kết sẽ không bao giờ đánh, và giao dịch sẽ không quá trình.

6

Tôi chắc bạn không phải tìm kiếm một giải pháp đóng cửa, hãy thử điều này cho một giải pháp nhỏ gọn hơn

try{ 
    DB::beginTransaction(); 

    /* 
    * Your DB code 
    * */ 

    DB::commit(); 
}catch(\Exception $e){ 
    DB::rollback(); 
} 
0

Nếu bất kỳ ngoại lệ xảy ra, các giao dịch sẽ rollback tự động.

định dạng giao dịch Laravel Basic

try{ 
    DB::beginTransaction(); 

    /* 
    * SQL operation one 
    * SQL operation two 
    ..................  
    ..................  
    * SQL operation n */ 


    DB::commit(); 
    /* Transaction successful. */ 
}catch(\Exception $e){  

    DB::rollback(); 
    /* Transaction failed. */ 
} 
Các vấn đề liên quan