文件:任务调度
任務調度: 使用 schedule 方法定義任務的調度頻率,並透過 Cron 作業執行調度器。
Laravel 的任務排程可輕鬆定義和排程週期性任務,而無需使用系統的 Cron 作業。
使用 Laravel 的調度器來定義任務的執行頻率,並讓 Laravel 負責管理任務的執行。
創建任務
指令 php artisan make:command SendDailyReport
產生新的命令類,並在 app/Console/Commands/SendDailyReport.php
做任務邏輯
namespace App\Console\Commands;
use Illuminate\Console\Command;
class SendDailyReport extends Command
{
protected $signature = 'report:daily';
protected $description = 'Send a daily report';
public function __construct()
{
parent::__construct();
}
public function handle()
{
// 這裡放任務邏輯
$this->info('Daily report sent!');
}
}
調度任務
在 app/Console/Kernel.php
檔案中,定義任務調度的頻率
// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
// 每天晚上執行任務
$schedule->command('report:daily')->daily();
}
要讓 Laravel 的調度器運行,需要在伺服器上設定一個 Cron 作業來每分鐘運行 Laravel 的調度器:
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
文件:队列
佇列處理: 建立作業、設定佇列驅動、派發和處理佇列作業,最佳化應用程式的回應速度。
佇列允許將耗時的操作(如發送郵件、產生報告等)延遲處理,從而提高應用程式的回應速度。
配置隊列
在 .env
檔案中配置佇列驅動:
QUEUE_CONNECTION=database
運行遷移來建立隊伍列表:
php artisan queue:table
php artisan migrate
在 app/Jobs 目錄下產生一個新的作業類別檔案。編輯該文件以定義你的作業邏輯:
// app/Jobs/ProcessReport.php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ProcessReport implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct()
{
//
}
public function handle()
{
// 這裡放任務邏輯
\Log::info('Processing report...');
}
}
派發佇列作業
在控制器或其他地方派發佇列作業:
use App\Jobs\ProcessReport;
// 派發佇列作業
ProcessReport::dispatch();
處理佇列
指令 php artisan queue:work
,使用佇列工作進程來處理佇列作業。
💡 任務調度 Task Scheduling
可以定期執行特定的任務,例如清理過期的數據或發送電子郵件。Laravel 提供了一個方便的 API 來設定和管理這些任務。💡 隊列 Queues
把時間消耗的任務推遲到稍後執行,從而提升應用的響應速度。例如,發送電子郵件可以在使用者提交表單後立即進行,而實際的發送過程則在背景進行。
使用 Laravel 的任務調度 Task Scheduling 和隊列 Queues 每天執行一次發送郵件。
step 1:建立一個 Laravel 專案
第 2 天:Laravel 啟服務與請求的生命週期有說明如果已經安裝 PHP
、 Composer
和一個資料庫(如 MySQL
)的條件下,可以省略直接進入安裝 Laravel 對應版本,所以這裡直接下指令件立一個新專案
composer create-project --prefer-dist laravel/laravel sent-email
cd sent-email
php artsian serve
step 2:配置 gmail 郵件
文件:发送邮件
郵件設置:如何在.env
文件中配置郵件服務。
使用不同的郵件驅動:例如 SMTP、Mailgun、SendGrid 等。
發送郵件的不同方式:使用 Markdown、HTML 或純文本郵件。
郵件佇列:如何將郵件發送任務推送到隊列中以提升性能。
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
# 自己的 gmail,認證郵件服務器的帳戶,也就是用來登錄 gmail 的帳戶
MAIL_USERNAME=pol***bea***@gmail.com
# 自己的 gmail 密碼
MAIL_PASSWORD=***************
MAIL_ENCRYPTION=tls
# 發件人顯示的郵件地址,收件人可以看到郵件是從該地址發出的
MAIL_FROM_ADDRESS=pol***bea***@gmail.com
# 發件人名稱
MAIL_FROM_NAME="kuku"
step 3:建立 artisan 命令
下指令 php artisan make:command SendEmail
在 app/Console/Commands
中創建 SendEmail.php 的檔案,然後在 handle
方法增加發送郵件的邏輯
💡 這個命令通常是同步執行的,下指令
php artisan email:send pol***bea***@gmail.com
的時候,郵件將會立即發送
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Mail;
class SendEmail extends Command
{
/**
* The name and signature of the console command.
* 命令的簽名
*
* @var string
*/
protected $signature = 'email:send {email}';
/**
* The console command description.
* 運行 php artisan list 或 php artisan help email:send 時會顯示這個描述
*
* @var string
*/
protected $description = 'Command description';
/**
* Execute the console command.
* 命令的執行邏輯,handle 方法會在命令被執行時自動調用
*/
public function handle()
{
// 從命令的參數中獲取 email 值,這將是用戶在執行命令時傳遞的電子郵件地址
$email = $this->argument('email');
/**
* 用 Mail Facade 的 raw 方法發送一封純文本郵件
* 第一個參數是郵件內容
* 第二個參數是一個回調函數,用於設置郵件的細節(如收件人和主題)
*/
Mail::raw('This is a test email!', function ($message) use ($email) {
$message->to($email)
->subject('Test Email');
});
// 命令執行完成後,使用 info 方法輸出一條成功信息,告訴用戶郵件已成功發送
$this->info("成功發送信件給 {$email}");
}
}
step 4:設定任務調度
打開 app/Console/Kernel.php
,並在 schedule
方法中加入命令,這個命令將每天自動執行發送郵件
/**
* Define the application's command schedule.
*/
protected function schedule(Schedule $schedule): void
{
// $schedule->command('inspire')->hourly();
$schedule->command('email:send pol***bea***@gmail.com')->daily();
}
step 5:建立隊列任務
指令 php artisan make:job SendEmailJob
,並在 app/Jobs/SendEmailJob.php
寫發送郵件的邏輯
💡 這裡是一個作 job,跟 step 3 的命令不太一樣,任務推送到隊列時,實際的郵件發送是在後台進行的。
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
/**
* OOPs 的 Abstraction 抽象,這個類實現了 ShouldQueue 接口,表示這是一個隊列任務
*
*/
class SendEmailJob implements ShouldQueue
{
/**
* Dispatchable:允許這個任務被分派到隊列中
* InteractsWithQueue:允許與隊列交互,例如檢查任務狀態
* Queueable:允許使用者設置與隊列相關的選項
*/
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $email;
/**
* Create a new job instance.
*/
public function __construct($email)
{
// 創建 SendEmailJob 實例時初始化 $email 屬性
$this->email = $email;
}
/**
* Execute the job.
*/
public function handle(): void
{
Mail::raw('Queue 的隊列任務測試電子郵件!', function ($message) {
$message->to($this->email)
->subject('Test Email from Queue');
});
}
}
step 6:在控制器中推送任務到隊列並且建立路由呼叫
下指令 php artisan make:controller EmailController
建立控制器
<?php
namespace App\Http\Controllers;
use App\Jobs\SendEmailJob;
use Illuminate\Http\Request;
class EmailController extends Controller
{
public function sendEmail(Request $request)
{
$email = $request->input('email');
SendEmailJob::dispatch($email);
return response()->json(['message' => '電子郵件將很快發送!']);
}
}
use App\Http\Controllers\EmailController;
Route::post('/send-email', [EmailController::class, 'sendEmail']);
step 7:運行隊列工作者
指令 php artisan queue:work
step 8:Test
用 postman 發送 POST 請求到 http://127.0.0.1:8000/api/send-email
,並傳送一個 JSON 物件參數,包含 email 屬性
{
"email": "123@test.com"
}
💡 解決方法:
方法 1:如果遇到以上問題,可以嘗試降低自己的信箱安全性應用程式 (參考文章:Gmail用戶如何設定允許低安全性應用程式存取帳戶)
方法 2:Laravel 使用 Mailgun 發送Email