Laravel Queue Scheduled Task 教學 範例
Laravel PHP

Laravel Queue & Scheduled Task 教學、範例

商業,創業,業務,職涯,美食,葡萄酒,閱讀,網路科技。

從 Larry 創業以及商業的經驗,希望以白話的口吻,介紹給大家這個商業的世界。

FB粉專會頻繁地分享以上主題,我最近也滿常使用Threads,歡迎大家追蹤互動~

圖片來源 https://github.com/laravel/laravel

******* 以下是以 Laravel 5.5 而言 *******

Queues

https://laravel.com/docs/5.5/queues
首先請看 config/queue.php,裡面 connections 選項有 database, redis 等選項,知道有這些選項就可以了,這部分我們不用動。一般使用 database 當 driver,將 .env 中的 QUEUE_DRIVER=database. QUEUE_DRIVER 預設是 sync, 注意當 QUEUE_DRIVER=sync 時基本上他就不是 queue, 在 loading page 時可以明顯感到他是 sync 在工作。

如果你是用 QUEUE_DRIVER=database, 要執行

php artisan queue:table
php artisan migrate

會在 DB 裡生成一 jobs table. 執行

php artisan make:job YourQueueJobClassName

會在 app/Jobs 底下新增 YourQueueJobClassName.php (本來不存在 app/Jobs 資料夾)

class YourQueueJobClassName 基本上有兩個 function:constructorhandle. 如官方教程範例

class ProcessPodcast implements ShouldQueue
{
    use InteractsWithQueue, Queueable, SerializesModels;

    protected $podcast;

    /**
     * Create a new job instance.
     *
     * @param  Podcast  $podcast
     * @return void
     */
    public function __construct(Podcast $podcast)
    {
        $this->podcast = $podcast;
    }

    /**
     * Execute the job.
     *
     * @param  AudioProcessor  $processor
     * @return void
     */
    public function handle(AudioProcessor $processor)
    {
        // Process uploaded podcast...
    }
}

這裡使用 dependency injection pattern. 在 constructor type-hint / inject 進來,用 local 變數接住,然後在 function handle 做事。

把 dependency injection 跟 function handle 寫完之後,queue job 的內容就完成了。在觸發 queue job 的地方使用 dispatch helper

dispatch(new ProcessPodcast($podcast));

注意,到此為止你的工作只會被寫到 DB jobs table, 並不會被執行。你需要啟動 queue worker process. 官方教程建議安裝 supervisor 套件,安裝好之後執行 service supervisor restart, 之後就依照官方教程編輯 laravel-worker.conf (以 Ubuntu 來說路徑是 /etc/supervisor/conf.d/laravel-worker.conf)

laravel-worker.conf 中的 command 要換成你專案的路徑,queue:work sqs 要換成 queue:work database (如果你的 .env QUEUE_DRIVER=database), user 欄位要換成你的 user name, stdout_logfile 要換成你專案的路徑。

編輯好 laravel-worker.conf 後執行

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*

這樣一個 queue 系統就可以運行了。

Task Scheduling

https://laravel.com/docs/5.5/scheduling
首先將底下這行加到 server 的排程 (crontab -e)

* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1

可以直接在 App\Console\Kernel 中的 schedule method 寫你的 scheduled tasks

$schedule->call(function () {
       // ...
})->daily();  // 每日

教程提到,你也可以排程 artisan commands 或是作業系統 commands. 如何寫你的 artisan commands 呢?

https://laravel.com/docs/5.5/artisan#generating-commands
如教程例子,執行

php artisan make:command SendEmails

他會在 app/Console/Commands 新增 SendEmails.php (Commands folder 預設是不存在)。SendEmails.php 中先編輯 signature, description 兩個變數,這兩個變數就是 command name 和 description. 確認你的 App\Console\Kernel commands method 是否如下

protected function commands()
{
    $this->load(__DIR__.'/Commands');

    require base_path('routes/console.php');
}

如果是的話,所有在 app/Console/Commands 底下的 command 都會被自動註冊,包含我們剛剛新增的 command.

這樣 php artisan list 就會看到你剛寫的 command, signature, description. 接著可以開始編輯你的 command 的工作內容,以上方範例而言:SendEmails. 教程有一段

“For greater code reuse, it is good practice to keep your console commands light and let them defer to application services to accomplish their tasks. In the example below, note that we inject a service class to do the “heavy lifting” of sending the e-mails.”

盡量把工作內容寫在 service 裡而不是全寫在 command 裡。好處是 1. 工作內容可以較好的模組化 2. 一些內部 class (例如 ORM classes) 不會直接被 command access, 多一層保護與檢查。

除了 define command class 外,另外也可以 define Closure Commands. 在 App\Console\Kernel, commands method 會 load routes/console.php. routes/console.php 中預設

Artisan::command('inspire', function () {
    $this->comment(Inspiring::quote());
})->describe('Display an inspiring quote');

這就是 Closure Command 的範例,如果嫌上方新增 command class 麻煩,也可以參考這個 command inspire, 直接寫在 routes/console.php 裡。

App\Console\Kernel schedule method 打開 $schedule->command('inspire') 這個 inspire command 就會被執行。

以上大概就是 scheduled tasks 跟 custom artisan command 的部分~

商業,創業,業務,職涯,美食,葡萄酒,閱讀,網路科技。

從 Larry 創業以及商業的經驗,希望以白話的口吻,介紹給大家這個商業的世界。

FB粉專會頻繁地分享以上主題,我最近也滿常使用Threads,歡迎大家追蹤互動~