Linux の cron(スケジューラー)と組み合わせて通知メール【 Laravel 】

前回、Linux の cron を使ってスケジュール実行をしました。

今回は実際に PHP のプログラムと絡めて、通知メールを作成したいと思います。

 

やりたいこと

訪問した会社から3ヵ月経過している会社をメールで知らせてくれるSFAのような機能を作りたいと思います。

送信先のメールは users テーブルに登録されているメールアドレスを対象とします。

 

前提条件

cron はすでにインストールされているとします。

Dockerをお使いの場合は以下のように Dockerfile に cron をインストールしておきましょう。


:
# ミドルウェアのインストール
RUN apt-get update \
&& apt-get install -y \
git \
zip \
unzip \
vim \
libpng-dev \
libpq-dev \
cron \
&& docker-php-ext-install pdo_mysql
:

 

手順

 

1)DBのテーブル作成

「会社テーブル(companies)」を以下のように作成します。

訪問した時間(visited_time)はあとで計算して通知メールを飛ばします。

 

「ユーザテーブル(users)」は以下のように作成します。

Laravel の認証機能(auth)を作るときに作られるテーブルで OK です。

 

2)ルーティング

ルーティングは以下のように設定します。


Route::get('mail_demo1','MailController@demo1');

 

crul で http://localhost/mail_demo1 を叩くと通知メールが実行される仕組みになります。

【 curl 】
curl とは主に UNIX 系 OS でよく利用されるコマンドおよびプログラムの一つ。様々なプロトコル(FTP、HTTP、HTTPS)を用いて URL で示されるネットワーク上の場所との間でデータの送受信を行うもの。

 

3)コントローラの作成

MailController の demo1 メソッドを以下のように記述していきます。


class MailController extends Controller
{
    public function demo1()
    {
        /*-------------------------------------
         * メール送信先の取得
         ------------------------------------*/
        //結果データの取得
        $users = \DB::table('users')->get();

        //複数の宛先
        foreach($users as $user){
            $emails[] = $user->email;
        }

        /*-------------------------------------
         * 訪問期間があいている会社名の取得
         ------------------------------------*/
        //結果データの取得
        $companies = \DB::table('companies')->get();

        $company_names = [];        // 宣言

        foreach($companies as $company){
            $time1 = strtotime($company->visited_time);
            $time2 = time();
            $diff_time = ($time2-$time1) / (60 * 60 * 24);

            //訪問日から180日以上の会社名を取得
            if($diff_time >= 180){
                $company_names[]=$company->place_name;
            }
        }

        /*-------------------------------------
         * メール送信処理
         ------------------------------------*/
        if(!empty($company_names)){     //会社名が空でない場合のみメール送信
            foreach($emails as $email) {
                //メール送信(テキスト)
                \Mail::send(array('text' => 'email.message_demo1'), ["company_names" => $company_names], function($message) use ($email){
                    $message->from('us@example.com');
                    $message->to($email)->subject('メール送信デモ');
                });
            }
        }
        return view('mail_demo');
    }
}

 

ビューである mail_demo.blade.php は「テスト通知メール完了」とだけ記述すればいいでしょう。

 

4)メール本文の作成

Mail ファサードの send() メソッドに入れているメール本文、 message_demo1.blade.php を以下のように記述します。


これはデモのメールです。

訪問してから3カ月以上経過している会社は以下になります。
<?php
foreach($company_names as $company_name){
   echo $company_name."\n";
}
?>

 

5)メール送信(ログに出力)

今回は実際にメール送信するのではなく、Laravelのログファイルに出力されるようにします。

envファイルにある MAIL_DRIVER に log と記述してあげます。


# .env
MAIL_DRIVER = log
:

 

詳しくは以下のページをご参照ください。

 

6)cron(スケジューラー)の設定

以下のコマンドを打って、cronを設定します。


$ crontab -e

 

viエディタが開くので以下のように記述します。


# 5分ごとに http://localhost/mail_demo1 にアクセス
*/5 * * * * curl --request GET 'http://localhost/mail_demo1'

 

【 curl コマンド 】
HTTPアクセスをしてコンテンツを取得できるコマンド。wgetコマンドでも同じようなことができる。


# URL をパラメータにしてそのコンテンツを標準出力させるのが、基本的な使い方
$ curl http://www.example.com/

 

実演

 

7)動作確認

ログは storage/logs/laravel.log に書き込まれます。

ログローテーションにしたい場合は confi/app.php の設定を変更してやります。

5分後にメールが書き込まれるか確認してみましょう。

以下のように書き込まれていれば OK です。

訪問日から3ヵ月以上経過している会社名だけメール本文に表示されればOKです。

 
以上です。

本庄マサノリ

仕事で Laravel を使っています。気づいたことや新しい発見など情報を発信していきます。問い合わせはこちら

>> Twitter をフォローする

 

-実践知識