iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 20
0
Modern Web

Laravel 6.0 初體驗!怎麼用最新的 laravel 架網站!系列 第 20

[Day 20] 刪除文章但是不刪除資料!聊 Soft Delete

接著,就是刪除文章了對吧!應該跟前面的新增修改沒有什麼兩樣吧。

這時候!我們突然接到了一個需求:

「是這樣,因為很多用戶常常會希望能復原之前不小心刪掉的內容,所以不知道可不可以,文章看起來刪掉了,但是實際上沒有刪掉呢?」

可以的!這時候我們就要來介紹 Laravel 物件另一個特別的功能:軟刪除(Soft Delete)!

什麼是軟刪除

前面的需求來說,我們可以想到,勢必在使用者刪除掉我們的資料時,我們資料庫內的資料,不會真的刪除,而是加上某個標籤,標記我們「刪除」了這筆資料。

這個判斷的邏輯,在 Laravel 裡面,也已經打包好囉!我們就直接來實作看看

建立軟刪除

資料庫 migration

我們先幫 Post 增加一個 migration 看看

$ php artisan make:migration add_soft_delete_to_posts_table
Created Migration: 2019_09_22_142336_add_soft_delete_to_posts_table

然後,我們改寫一下這個 migration

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddSoftDeleteToPostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('posts', function (Blueprint $table) {
            $table->softDeletes();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        //
    }
}

我們利用 Laravel 提供的函式,幫助我們快速建立軟刪除相關的欄位。

接著,我們跑一下 migration

$ php artisan migrate
Migrating: 2019_09_22_142336_add_soft_delete_to_posts_table
Migrated:  2019_09_22_142336_add_soft_delete_to_posts_table (0.8 seconds)

成功的話,回去看看資料庫的 posts 資料表,應該可以看到多了一個 deleted_at 欄位,這樣我們資料表就準備完成囉!


不過,我們還是要養成記得處理 migration down() 的好習慣,以免之後 rollback 失敗造成困擾。

我們改寫剛剛 migration 的 down() 函式

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::table('posts', function (Blueprint $table) {
        $table->dropSoftDeletes();
    });
}

加上了 dropSoftDeletes(),我們測試看看

php artisan migrate:rollback --step=1
Rolling back: 2019_09_22_142336_add_soft_delete_to_posts_table
Rolled back:  2019_09_22_142336_add_soft_delete_to_posts_table (0.64 seconds)

跑完之後,如果可以看到 deleted_at 從資料表中消失,那就代表我們成功囉!

接著我們再執行一次 php artisan migrate,確認資料表格式是我們需要的樣子後,開始在物件裡加上軟刪除

在 Eloquent 裡面加上軟刪除

我們在 Post 物件最前面,加上 use SoftDeletes;

use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
    use SoftDeletes;

好了,完成了。

簡單的很不可思議吧!我們嘗試用測試路徑刪掉一筆資料看看

Route::get('/test', function(){
    $post = Post::find(1);
    $post->delete();
});

然後點擊 http://127.0.0.1/test 之後,看看資料庫的資料

成功的話,應該可以看到 id 為 1 的資料,deleted_at 不再是 NULL 了,而是一個時間戳記!

這時候我們嘗試存取 id 為 1 的 Post

Route::get('/test', function(){
    $post = Post::find(1);
    return $post;
});

點擊 http://127.0.0.1/test 之後,什麼都看不到!我們成功了!

刪除路徑

軟刪除的設置做完之後,我們就可以來建立刪除的路徑了。

我們在編輯文章的頁面裡面,加上一個刪除文章的按鈕

改寫 resources/views/edit.blade.php 如下

編輯文章

<form action="{{ route('posts.update', [ 'post' => $post]) }}" method="POST">
    @method('PUT')
    @csrf
    <label>內容:
        <textarea name="content">{{ $post->content }}</textarea>
    </label><br>
    <input type="submit" value="送出文章">
</form>
<form action="{{ route('posts.destroy', [ 'post' => $post]) }}" method="POST">
    @method('DELETE')
    @csrf
    <input type="submit" value="刪除文章">
</form>

這樣,在編輯文章的畫面下,我們就多了一個刪除文章的表單,裡面只包含一個按鈕:「刪除文章」。

接著我們改寫 PostControllerdestroy()

public function destroy(Post $post)
{
    $post->delete();
    return redirect(route('posts.index'));
}

好了!我們隨便選一篇文章的編輯頁面(比方說 http://127.0.0.1/posts/3/edit ),然後點下「刪除文章」的按鈕。

點完之後,我們到資料庫看看該文章的資料,順利的話應該可以看到 id 為 3 的文章,deleted_at 欄位已經加上時間戳記,代表我們文章已經刪除囉!這時我們再次嘗試進入 http://127.0.0.1/posts/3/edit 時,應該會看見 「404 Not Found」 的字樣

想要把文章復原,只要我們在資料庫裡面,把對應資料的 deleted_at 改成 NULL,文章就會正常顯示,也可以正常的編輯囉!

到這邊,我們對文章的所有動作,正式告一段落了!


小小總結一下今天我們學到些什麼。

今天我們學到什麼是軟刪除,怎麼利用 Laravel 快速的建立軟刪除的資料,還學到怎麼建立刪除的功能。

希望各位讀者覺得今天的文章有學到東西,我們明天見!


上一篇
[Day 19] 繼續聊文章!怎麼透過表單編輯文章
下一篇
[Day 21] 和資料庫相關的測試!怎麼測試資料庫的存取
系列文
Laravel 6.0 初體驗!怎麼用最新的 laravel 架網站!30

2 則留言

0
Lucas
iT邦新手 5 級 ‧ 2019-09-23 21:01:48

SoftDeletes Trait 需引入 namespace:

use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
    use SoftDeletes;

對!我忽略這一段了,感謝!

0
ckp6250
iT邦新手 2 級 ‧ 2019-11-28 15:48:31

請問老師,
假設某筆文章被改了三次,
laravle 有沒有類似 Soft Delete 這樣的機制,
可以追蹤這三次修改的內容,而且可以回溯到任何一次的原始內容?

我要留言

立即登入留言