本文方法是利用Linux的crontab定時任務來協助實現Laravel的任務排程
一、建立專案
1、開啟終端,執行命令:laravel new crontab
,包括資料庫,確保本地能正常執行。隨後部署上線。phpstrom
連線伺服器,確保程式碼可以正常提交到伺服器。
2、建立任務類,終端執行命令:php artisan make:command SendEmail
3、修改 SendEmail.php
檔案
protected $signature = 'email:send';
protected $description = '定時發郵件測試';
4、先不慌做發郵件,先來個檔案定時寫入測試,在檔案中寫入當前時間,程式碼如下
public function handle()
{
//寫入檔案
file_put_contents("/var/www/crontab/file.txt", date('Y-m-d H:i:s') . PHP_EOL, FILE_APPEND);
}
注:這裡的PHP_EOL
代表時間列表換行,後面的FILE_APPEND
是指往後追加一條記錄。
5、修改app/Console/Kernel.php
檔案:
protected $commands = [
Commands\SendEmail::class //註冊任務類
];
protected function schedule(Schedule $schedule)
{
//每分鐘執行一次檔案的寫入
$schedule->command('email:send')
->everyMinute();
}
6、伺服器上,進入專案:cd /var/www/crontab
,先檢視伺服器上PHP
安裝路徑,執行命令:which php
,我的PHP
路徑是/usr/bin/php
,然後把路徑複製儲存下來,接著執行命令:crontab -e
,選擇開啟方式,建議選擇第4個。在最後一行增加如下程式碼:
* * * * * /usr/bin/php /var/www/crontab/artisan schedule:run >> /dev/null 2>&1
注:這裡前面一部分/usr/bin/php
代表伺服器上PHP
的安裝路徑,後面一部分代表專案目錄。
另外上面的命令前面的5個星號*分別代表分鐘、小時、天、月、星期。
分鐘:0-59的整數,預設星號和星號/1 代表1分鐘。
小時:0-23的整數。
天:1-31的整數。
月:1-12的整數。
星期:0-7的整數,0和7都代表星期日。
crontab -l 可以列出當前的定時任務。
7、啟動任務sudo service cron restart
,開啟FZ
,檢視伺服器上專案的根目錄下的file.txt
檔案中是否有時間寫入並且每分鐘執行一次。確認成功後,執行命令 service cron stop
和 exit
退出定時任務。
二、實現定時發郵件
接下來要做的是把寫入檔案的操作換成定時發郵件。在.env
檔案配置發郵件所需的相關資訊。
MAIL_DRIVER=smtp
MAIL_HOST=smtp.qq.com
MAIL_PORT=465
MAIL_USERNAME=244500972@qq.com
MAIL_PASSWORD=***** //填自己的郵箱密碼
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS=244500972@qq.com
MAIL_FROM_NAME=huangdj
1、開啟web.php
,新增路由
$this->any('mail', 'HomeController@mail');//發郵件
2、在Home
控制器中新增如下程式碼:
public function mail()
{
//第一種方法
\Mail::raw('定時傳送郵件 測試', function ($message) {
$message->from('244500972@qq.com', '長樂未央');
$message->subject('郵件主題 測試');
$message->to('244500972@qq.com');
});
//第二種方法
// \Mail::send('admin.mail', ['name' => 'holy'], function ($message) {
// $message->to('244500972@qq.com');
// });
}
測試:終端列印路由,拿到路由地址去瀏覽器中訪問:http://你的二級域名/admin/mail
,檢視郵箱是否收到郵件。如果成功收到郵件,請繼續往下。。
3、開啟任務類 SendEmail.php
檔案,修改handle
方法,程式碼如下:
public function handle()
{
//寫入檔案
// file_put_contents("/var/www/crontab/file.txt", date('Y-m-d H:i:s') . PHP_EOL, FILE_APPEND);
\Mail::raw('定時傳送郵件 測試', function ($message) {
//查出要發郵件的所有使用者的郵箱
$customers = Customer::where('email', '<>', null)->get();
foreach ($customers as $customer) {
$message->from('244500972@qq.com', 'huangdj');
$message->subject('郵件主題 測試');
//執行傳送
$message->bcc($customer->email);
}
});
}
最後去伺服器的當前專案中,啟動定時命令 service cron restart
,等一分鐘,檢視郵箱是否收到郵件並且每一分鐘執行一次。
三、增加Redis佇列
當我們要發的郵件量很大時,我們就要使用到佇列,把要傳送的郵件全部存入佇列,讓後端去完成這個漫長的操作。網上很多資料都是使用資料庫佇列,我這裡使用 redis
佇列。
1、修改.env檔案中的 QUEUE_DRIVER=sync
為 QUEUE_DRIVER=redis
2、啟動佇列,終端執行命令:redis-server
,你會發現predis
的擴充套件沒裝,執行命令:composer require predis/predis
安裝即可。安裝完成後,重新啟動redis。
3、建立任務類:php artisan make:job SendReminderEmail
,執行成功後會在app/Jobs
目錄下生成一個SendReminderEmail.php
,我們修改其內容如下:
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use App\Customer;
use Illuminate\Contracts\Mail\Mailer;
class SendReminderEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $customer;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(Customer $customer)
{
$this->customer = $customer;
}
/**
* Execute the job.
*
* @return void
*/
public function handle(Mailer $mailer)
{
$customer = $this->customer;
$mailer->send('emails.reminder',['customer'=>$customer],function($message) use ($customer){
$message->to($customer->email)->subject('新功能釋出');
});
}
}
4、建立郵件區域性檢視resources/views/emails/reminder.blade.php
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div>
親愛的{{$customer->nickname}},您好,長樂未央新發布了Laravel5.6使用redis實現群發郵件功能,立即去體驗下吧:
<a href="https://www.whphp.com/">前往長樂未央</a>
</div>
</body>
</html>
四、推送佇列任務---手動分發任務
1、在web.php
中新增如下路由:
Route::get('mail/sendReminderEmail/{id}','MailController@sendReminderEmail');
2、建立控制器:php artisan make:controller MailController
,控制器中寫入如下程式碼:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Customer;
use Mail;
use Storage;
use App\Jobs\SendReminderEmail;
class MailController extends Controller
{
//傳送提醒郵件
public function sendReminderEmail(Request $request, $id)
{
$customer = Customer::findOrFail($id);
$this->dispatch(new SendReminderEmail($customer));
}
}
3、執行佇列監聽器。在瀏覽器中訪問http://你的二級域名/mail/sendReminderEmail/63
,此時任務被推送到Redis
佇列中。在命令列中執行如下命令:php artisan queue:work
,然後去檢視郵箱會收到提醒郵件:
4、推送任務到指定佇列,修改App\Console\Commands\SendEmail
裡面的handle
方法程式碼如下:
public function handle()
{
\Mail::queue('定時傳送郵件 測試', function ($message) {
//查出要發郵件的所有使用者的郵箱
$customers = Customer::where('email', '<>', null)->get();
foreach ($customers as $customer) {
$message->from('244500972@qq.com', 'huangdj');
$message->subject('郵件主題 測試');
//執行傳送
//$message->bcc($customer->email);
//將任務推送到指定佇列並延遲一分鐘執行
dispatch(new \App\Jobs\SendReminderEmail($customer->email))->onQueue('emails')->delay(60);
}
});
}
終極測試:看郵箱是否是每隔一分鐘收到一份郵件
啟動:redis-server
啟動:php artisan queue:work
啟動定時執行:service cron restart
參考文獻:http://laravelacademy.org/post/2012.html
http://laravelacademy.org/post/222.html#ipt_kb_toc_222_14
本作品採用《CC 協議》,轉載必須註明作者和本文連結