Lam's blog

知之爲知之,不知爲不知


  • 首頁

  • 歸檔

  • 關於我

  • 搜索

在Laravel 8中更好的使用數據庫事務

時間: 2021-11-25   |   分類: PHP   | 字數: 629 字 | 閱讀: 2分鐘 | 閱讀次數:

使用數據庫的事務機制是保證數據完整性的有效方法,將幾條數據操作語句放到一個事務組裏,這些語句要麽全部成功,要麽全部失敗。

$user = User::create([...]);

Team::create([
    'owner_id' => $user->id,
    ...
]);

上面的代碼沒有使用事務機制,假如Team::create執行失敗,那該用戶就會出現無分組(team)的情況。為了避免上述情況發生,可以將它們包含在事務之中:

DB::transaction(function(){
    $user = User::create([...]);

    Team::create([
        'owner_id' => $user->id,
        ...
    ]);
});

然後,數據庫的事務機制只是針對數據執行語句實現原子性。而在事務中的其它代碼即使事務未commit,也會正常運行。

DB::transaction(function(){
    $user = User::create([...]);

    Mail::to($user)->send(new WelcomeEmail());

    Team::create([
        'owner_id' => $user->id,
        ...
    ]);
});

在上面例子中,歡迎郵件(WelcomeEmail)無論用戶team是否創建成功均會發送,這顯然不符合我們的預期。

一般的修復方式是將歡迎郵件移出事務外面。

DB::transaction(function(){
    $user = User::create([...]);

    Team::create([
        'owner_id' => $user->id,
        ...
    ]);
});

Mail::to($user)->send(new WelcomeEmail());

現在即使事務失敗,將會拋出異常,不會執行下面的代碼。但是在大多數情況下,代碼不會直接這樣子寫,可能發送郵件的代碼在User::create()後觸發UserCreated進行發送,這樣又會出現上面的情況。

在Laravelv8.19.0開始,可以通過閉包的方式把代碼包含進去,閉包裏面的代碼只能在事務全部提交commit之後才會執行。

class SendWelcomeEmail{
    public function handle()
    {
        DB::afterCommit(function(){
            Mail::to($user)->send(new WelcomeEmail());
        });
    }    
}

這個看起來似乎不夠優雅,Laravel還允許你這樣子寫來實現相同功能:

class SendWelcomeEmail{
    public $afterCommit = true;

    public function handle()
    {
        Mail::to($user)->send(new WelcomeEmail());
    }    
}

留意上面類中的$afterCommit屬性。

接下來看怎麽在事務中使用:

DB::transaction(function(){
    $user = User::create([...]);

    SendWelcomeEmail::dispatch($user);

    Team::create([
        'owner_id' => $user->id,
        ...
    ]);
});

SendWelcomeEmail會被分配到隊列中進行處理,隊列配置具體不表。

#PHP# #Laravel#

聲明:在Laravel 8中更好的使用數據庫事務

鏈接:https://www.lamsir.cc/post/better-management-of-database-transactions-in-laravel-8/

作者:Lam Sir

聲明: 本博客文章除特別聲明外,均采用 CC BY-NC-SA 3.0許可協議,轉載請註明出處!

創作實屬不易,如有幫助,那就打賞博主些許茶錢吧 ^_^
ETH Pay

ERC20-USDT

基於Python的權重隨機數
Astra vs Divi 主題比較
Lam Sir

Lam Sir

Live your life...

30 日誌
5 分類
11 標簽
標簽雲
  • Python
  • Php
  • Javascript
  • Mysql
  • Video
  • Wordpress
  • API
  • Laravel
  • MAC
  • Node.Js
© 2020 - 2022 Lam's blog
0%