3分鐘短文:再述Laravel模型的“軟刪除”

程式設計師小助手發表於2020-10-08

引言

我們不止一次在系列文章中講到模型的“軟刪除”功能,因為現實場景中為了保證資料可追溯,我們幾乎不會對資料庫進行物理刪除。刪除資料有可能會造成資料一致性的破壞,進而導致業務邏輯無法跑通。所以,軟刪除的概念,極為重要。

img

本文我們仍然不厭其煩地講解軟刪除的功能。

物理刪除

其實就是真實地把資料從資料庫條目清除,laravel模型提供了開箱即用的方法。比如下面這樣使用:

$event = Event::find(12);
$event->delete();

首先使用primary key查詢出需要的條目,返回一個Event物件例項,然後呼叫 delete 方法進行刪除。真實的SQL如下:

DELETE FROM events WHERE id = 12;

laravel提供了許多語法糖,上面使用 find 和 delete 兩個步驟,可以縮減為一個方法 destroy,用法如下:

Event::destroy(12);

這樣一行就搞定了。

軟刪除

在許多情況下,你不會真正想要從資料庫中刪除記錄,而是用一種不再在應用程式中顯示它們的方式對其進行註釋。這就是所謂的軟刪除。

Laravel本身支援軟刪除,只需要進行少量的配置更改,以確保在執行delete或destroy時,模型的記錄不會被實際刪除。作為一個例子,我們修改Event模型以支援軟刪除。

首先建立一個新的遷移,將名為deleted_at的列新增到events表中:

php artisan make:migration add_soft_delete_to_events --table=events

執行成功,輸出內容如下:

Created Migration: 2020_10_08_184402_add_soft_delete_to_events

接著在生成的遷移檔案內實現遷移使用的 up 方法:

public function up()
{
    Schema::table('events', function(Blueprint $table)
    {
        $table->softDeletes();
    });
}

還有用於遷移回滾的 down 方法:

public function down()
{
    Schema::table('events', function(Blueprint $table)
    {
        $table->dropColumn('deleted_at');
    });
}

修改完畢,在命令列執行遷移指令:

php artisan migrate

執行成功輸出內容:

Migrating: 2020_10_08_184402_add_soft_delete_to_events
Migrated: 2020_10_08_184402_add_soft_delete_to_events

模型SoftDelete

有了資料庫表的支援,我們才能在模型內使用軟刪除的功能。

其實原理很簡單,就是為模型追加一個全域性作用域,為每個查詢子句追加上如下篩選條件:

WHERE deleted_at IS NULL

laravel已經為我們寫好這部分邏輯了,在模型內引入如下trait:

namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

在類內引入trait,並手動指定修改器,也就是說deleted_at欄位,我們使用 Carbon 進行例項化操作。

class Event extends Model {
    use SoftDeletes;
    protected $dates = ['created_at','deleted_at','started_at','updated_at'];
}

儲存這些更改之後,下次刪除與此模型關聯的記錄時,deleted_at列將被設定為當前時間。任何設定deleted_at為日期時間值的記錄,都不會包含在任何查詢結果中,因此看起來已經被刪除了

這樣操作非常有用,因為誤刪除的資料,隨時可以通過設定 deleted_at = null 而恢復到正常的業務流程中,比如刪除的使用者,刪除的訂單,等等其他資源。

如果你在程式碼內要堅持查詢全量資料,也包含軟刪除了的資料,那麼程式碼這樣寫:

$events = Event::withTrashed()->get();

寫在最後

本文我們有重溫了laravel的模型軟刪除功能,通過建立遷移檔案,修改資料庫表,追加軟刪除欄位。並在模型內引入 SoftDelete 程式碼片段引入軟刪除的程式功能。

Happy coding :-)

我是@程式設計師小助手,專注程式設計知識,圈子動態的IT領域原創作者

本作品採用《CC 協議》,轉載必須註明作者和本文連結
write-less-do-more-make-you-out-of-door

相關文章