iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 26
1

有了用戶系統,也做了測試,加上紀錄,甚至還知道怎麼把系統的資訊作加解密了。網站的服務基本上已經成形了。

不過,多數網站除了面對用戶的服務之外,常常還會有很多排程的行為要處理,比方說定期備份,或者資料清理等等。

今天,我們就來做一個資料清理的排程看看,每過一年就會將軟刪除的文章真的刪除掉!

用 Laravel 處理排程

過去的排程作法

在過去,如果網站框架不支援,要做這一類自動排程的行為,通常會選用 Cron Job 進行處理。

Laravel 的好處是,在框架下面幫 Cron Job 做了一個包裝,讓網站相關的排程進入程式碼,設置也更加簡便了。

我們先來實作一個排程看看!

建立排程

排程的程式建立在 App\Console\Kernel.php 裡面,我們在裡面將 schedule() 改寫成

protected function schedule(Schedule $schedule)
{
    $schedule->call(function () {
        Log::info('成功排程');
    })->everyMinute();
}

然後等幾分鐘。成功的話,我們應該可以在今天的 log 檔案裡面看到類似

[2019-09-28 xx:xx:02] local.INFO: 成功排程

之類的紀錄囉!

測試完之後,記得要將測試碼刪除或者註解掉,不然很快就要塞滿 Log 檔案了!

建立 Command

再來,就是實作我們前面所說的邏輯:將資料庫裡面軟刪除的物件真的刪除掉。

不過在實際寫程式之前,我們會發現,如果將這些邏輯都固定寫在 schedule() 裡面,時間一長 schedule() 一定會變得很肥大。

筆者自己常用的方式,是將需要排程的邏輯寫成 Laravel 的指令。這樣一來,schedule() 裡面就只需要做呼叫指令的行為了,除了時間之外,不需要包含太多的邏輯。

我們利用 Laravel 來產生指令

$ php artisan make:command ClearDeletedPosts
Console command created successfully.

然後,實作將軟刪除過的文章刪掉的邏輯。我們打開 app/Console/Commands/ClearDeletedPosts.php ,改寫

protected $signature = 'posts:clear';

這是之後指令的呼叫方式,之後使用 php artisan posts:clear 就可以實作裡面的邏輯。

再來,我們改寫

protected $description = '清除已刪除文章';

這是之後會出現在 php artisan 裡面,針對該指令的說明文字。

寫好之後,我們可以執行 php artisan 看看,應該會看到

 posts
  posts:clear          清除已刪除文章

這一段。

再來,就是實作邏輯了,我們改寫 handle(),利用 onlyTrashed() 來找到所有被軟刪除的文章。我們可以先透過 var_dump() 這個函式來印出 $posts 實際的內容,看看有沒有什麼問題。

public function handle()
{
    $posts = Post::onlyTrashed()->get();
    var_dump($posts);
}

這樣寫好之後,我們測試一下

$ php artisan post:clear

如果資料庫目前存在被刪除的文章,應該會看到類似

class Illuminate\Database\Eloquent\Collection#742 (1) {
  protected $items =>
  array(1) {
    [0] =>
    class App\Post#743 (27) {

的資料。

確認取得被刪除過的文章資料後,我們跑一個迴圈,利用 forceDelete() 將資料真正刪除,並多加上一筆 Log 紀錄。

public function handle()
{
    $posts = Post::onlyTrashed()->get();
    foreach($posts as $post){
        $post->forceDelete();
    }
    Log::info('移除所有被刪除文章');
    return;
}

寫好了之後,我們再執行一次 php artisan post:clear,應該就可以真的看到文章消失在資料庫中囉!

然後,我們把這個指令納入排程裡面,每一年執行一次

protected function schedule(Schedule $schedule)
{
    $schedule->command('post:clear')->yearly();
}

好了!我們的需求完成了!現在每一年,系統都會執行一次 post:clear 來把刪除掉的文章清理掉。如果我們自己覺得被刪除的文章實在太多,也可以手動執行 php artisan post:clear 來刪除所有文章。

是不是很方便呢?


小小總結一下今天我們所學到的東西。今天我們學到如何宣告排程,以及學會如何宣告指令,來協助排程邏輯。

希望今天各位讀者有收穫!我們明天見!


上一篇
[Day 25] 覺得自己的系統還不夠安全?用 laravel 快速的加解密!
下一篇
[Day 27] 多國語系的處理!聊 Laravel Localization
系列文
Laravel 6.0 初體驗!怎麼用最新的 laravel 架網站!30

尚未有邦友留言

立即登入留言