Laravel5.6 使用定時任務實現定時發郵件

huangdj 發表於 2019-09-11

本文方法是利用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 stopexit退出定時任務。

Laravel5.6 使用定時任務實現定時發郵件

二、實現定時發郵件

接下來要做的是把寫入檔案的操作換成定時發郵件。在.env檔案配置發郵件所需的相關資訊。

MAIL_DRIVER=smtp
MAIL_HOST=smtp.qq.com
MAIL_PORT=465
[email protected]
MAIL_PASSWORD=***** //填自己的郵箱密碼
MAIL_ENCRYPTION=ssl
[email protected]
MAIL_FROM_NAME=huangdj

1、開啟web.php,新增路由

$this->any('mail', '[email protected]');//發郵件

2、在Home控制器中新增如下程式碼:

public function mail()
{
   //第一種方法
   \Mail::raw('定時傳送郵件 測試', function ($message) {
       $message->from('[email protected]', '長樂未央');
       $message->subject('郵件主題 測試');
       $message->to('[email protected]');
   });

  //第二種方法
// \Mail::send('admin.mail', ['name' => 'holy'], function ($message) {
//     $message->to('[email protected]');
// });
}

測試:終端列印路由,拿到路由地址去瀏覽器中訪問: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('[email protected]', 'huangdj');
         $message->subject('郵件主題 測試');

          //執行傳送
         $message->bcc($customer->email);
      }
    });
}

最後去伺服器的當前專案中,啟動定時命令 service cron restart,等一分鐘,檢視郵箱是否收到郵件並且每一分鐘執行一次。

Laravel5.6 使用定時任務實現定時發郵件

三、增加Redis佇列

當我們要發的郵件量很大時,我們就要使用到佇列,把要傳送的郵件全部存入佇列,讓後端去完成這個漫長的操作。網上很多資料都是使用資料庫佇列,我這裡使用 redis佇列。

1、修改.env檔案中的 QUEUE_DRIVER=syncQUEUE_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}','[email protected]');

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,然後去檢視郵箱會收到提醒郵件:
Laravel5.6 使用定時任務實現定時發郵件

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('[email protected]', '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


相關文章

Laravel Passport OAuth 資料庫查詢改快取優化 資料庫|Laravel

Laravel Passport OAuth 資料庫查詢改快取優化

1、oauth_clients 表查詢快取修改-- 找到路徑 project/vendor/laravel/passport/src/Client.php 檔案註釋該行程式碼,不然查詢出來存快取無法獲
發現使用 Laravel 的許可權工具包不會使用,有同感的? Laravel

發現使用 Laravel 的許可權工具包不會使用,有同感的?

感覺看的有點懵,我不用工具包,自己建立表 用原生思路的程式碼寫 能寫 出來居於 auth 許可權控制選單按鈕的許可權管理,看來我還是太菜了 -,-
Laravel 多鍵路由繫結 Laravel

Laravel 多鍵路由繫結

Laravel 可以通過兩種方式進行路由模型繫結。在模型中指定路由的鍵/** * 獲取該模型的路由的自定義鍵名。 * * @return string */public function getRou
自定義 Command 檢視 Laravel 日誌 Laravel

自定義 Command 檢視 Laravel 日誌

Unix 的 tail 命令可以用來檢視檔案的,例如檢視 2019-09-26 的最後 100 行日誌$ cd storage/logs $ tail -100 laravel-2019-09-26
Laravel 實現多欄位登陸(超簡單,叫你如何不動腦子完成任務) Laravel

Laravel 實現多欄位登陸(超簡單,叫你如何不動腦子完成任務)

laravel 提供 username() 方法,來自定義 使用者名稱 登陸方式,所有 我們直接 修改 laravel 提供的Auth 的 LoginController 類;1.先驗證 使用者 提交
『輕鬆部署 Laravel 應用』系列文章快捷連結 Laravel

『輕鬆部署 Laravel 應用』系列文章快捷連結

Wi1dcard 同學的『輕鬆部署 Laravel 應用』系列文章快捷連結《開篇》《00. 登入伺服器》 《01. 寶塔皮膚》《02. 一鍵指令碼》 《03. 探尋一鍵指令碼》《04. 手動部署 -
Laravel/Homestead box v8.2.1 分享 Laravel

Laravel/Homestead box v8.2.1 分享

百度雲:https://pan.baidu.com/s/1oj9g9nAORLswYSvKr...密碼:kvf4
Laravel Vue 下拉框聯動小技巧 Vue|Laravel

Laravel Vue 下拉框聯動小技巧

最近在做一個後臺管理相關的東西,有一個關於下拉框聯動的小技巧可以分享給大家,寫好後不用更改前端程式碼,只需更改後端相應的配置,即可增加相對應的聯動。比如有兩個下拉框一個省和一個市的下拉框,這裡只是拿省
Laravel 模型關聯 「 預載入 」中 with () 方法的功能的示例及說明 Laravel

Laravel 模型關聯 「 預載入 」中 with () 方法的功能的示例及說明

laravel 模型關聯 「 預載入 」 -&gt;with()功能的示例1 模型關聯說明:在動態模型 Status中,指明一條微博動態屬於一個使用者 User&lt;?php..// 動態模型st
關於 Laravel 的一些個人見解 Laravel

關於 Laravel 的一些個人見解

Laravel 是一個全棧框架;我們使用 Laravel 開發業務常見有 3 個方向;1、前端頁面和後端邏輯混合的應用主要是面向對 SEO 有需求的專案;比如說新聞資訊部落格文章等;一般在控制器中 r
分享連結:序言《Laravel 之道》 Laravel

分享連結:序言《Laravel 之道》

分享連結:序言《Laravel 之道》
Laravelapi 自定義 response 格式 Laravel

Laravelapi 自定義 response 格式

laravel的http路由檔案有兩個api.php和web.php➜  ~ ll /Users/shiwenyuan/test/test_demo/routestotal 32drwxr-xr-x