eccube3からメルマガ機能をプラグインとして提供しました。お客様からは即時配信はもちろん、設定した配信日時になったら、メルマガを配信できるような運用も欲しいというご要望がありましたが、残念ながら、メルマガプラグインは配信日時指定(予約配信)機能を提供していなかったので、カスタマイズ化が必要と思います。
本書はeccube3のメルマガ配信日時指定(予約配信)機能の追加方法を記載します。
Contents
0.前提
事前に下記の前提条件を満たすのかを確認ください。(普通に条件を満たすでしょう)
・eccube3 メルマガプラグインをインストール済み
・crontabの編集権限を持つ
・サーバーファイルの権限を持つ
1.プラグインテーブルに配信日時カラムを追加
下図のように、テーブル: plg_send_historyにdatetime型の「配信日時:send」カラムを追加します。デフォルト値をnullに設定します。
2.Entityに属性(プロパティ)を追加
DBカラムに合わせて、「MailMagazine\Entity\MailMagazineSendHistory.php」にsend属性とget/setterメソッドを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
/** * @var \DateTime */ private $send; /** * Set send. * * @param \DateTime $send * * @return send */ public function setSend($send) { $this->send = $send; return $this; } /** * Get send. * * @return \DateTime */ public function getSend() { return $this->send; } |
3.Ymlファイルにfieldを追加
「MailMagazine\Resource\doctrine\Plugin.MailMagazine.Entity.MailMagazineSendHistory.dcm.yml」ファイルに、下記のfield:sendを追加します。
1 2 3 4 5 6 7 |
send: type: datetime nullable: true |
※ymlにタブとかを入れると、不具合が発生しますので、上記(スペースで整形)と全く同じように書きましょう。
4.入力画面の処理
ステップ1~3までは、MVC概念の中に、M層の基礎部分を整えました。これから、V層を改修します。
まずは、下図のように、メルマガプラグインの配信画面の一番下にて、「配信日時」項目を追加します。
「MailMagazine\Form\Type\MailMagazineType.php」ファイルに、buildFormメソッドの下(->add(‘htmlBody’, …の後ろ)に、配信日時を追加します。
※配信日時を入れないと、即時配信(もともと機能)になりますので、必須(required)は不要。
1 2 3 4 5 6 7 8 9 |
->add('send', 'datetime', array( 'label' => '配信日時', 'required' => false, )) |
次は、「MailMagazine\Resource\template\admin\template_select.twig」ファイルに、上記に設定した配信日時を設定します。
1 2 3 4 5 |
{{ form_row(form.send) }} |
5.確認画面の処理
初期表示完了の後に、配信日時を入力した場合、確認画面にて、その値を表示しなければならないため(当然の話)、確認画面にも配信日時を追加します。
まずは、「MailMagazine\Controller\MailMagazineController.php」のconfirmメソッドに、確認画面に必要な配信日時(send_itm)を設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$send = """"; if( !empty($form['send']->getData()) ){ $send = $form['send']->getData()->format('Y-m-d H:i'); } return $app->render('MailMagazine/Resource/template/admin/confirm.twig', array( 'form' => $form->createView(), 'subject_itm' => $form['subject']->getData(), 'body_itm' => $form['body']->getData(), 'htmlBody_itm' => $form['htmlBody']->getData(), 'id' => $id, 'send_itm' => $send, 'testMailTo' => $service->getAdminEmail(), )); |
続いて、「MailMagazine\Resource\template\admin\confirm.twig」テンプレートファイルに、先ほど追加した配信日時を画面に表示します。
1 2 3 4 5 6 7 8 |
<tr> <th style=""width: 20%;"">送信日時</th> <td>{{ send_itm }}</td> </tr> |
6.登録処理
即時配信ではないので、画面に設定した配信日時を一旦DBに保存しなければなりません。
メルマガの即時配信機能は「配信する」ボタンを押したら、即時に配信するため、その挙動に影響を与えないように、「MailMagazine\Controller\MailMagazineController.php」のprepareメソッドに下記のような改修が必要です。
1 2 3 4 5 6 7 8 9 10 11 |
//下記を追加 if( empty($data['send'])){ //下記は既存のため、追加不要 // フラッシュスコープにIDを保持してリダイレクト後に送信処理を開始できるようにする $app['session']->getFlashBag()->add('eccube.plugin.mailmagazine.history', $sendId); } |
最後に、「MailMagazine\Service\MailMagazineService.php」のcreateMailMagazineHistoryメソッドに配信日時を保存します。
1 2 3 4 5 6 7 8 9 |
$sendHistory->setCreateDate($currentDatetime); $sendHistory->setStartDate($currentDatetime); //下記を追加 $sendHistory->setSend($formData['send']); |
7.新規配信処理を追加
時間が設定した配信日時になったら、配信処理を行うために、該当処理を追加します。
考え方は、配信完了日付はnull(まだ配信しない)尚且つ配信日時が過去直近の5分内のメルマガがあれば、既存の配信処理を使い回し、配信処理(配信完了日付の更新処理を含む)を行う。
「MailMagazine\Controller\MailMagazineController.php」に、新規メソッド:fcommitを下記のように追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
/** * 配信処理 * 配信終了後配信履歴に遷移する * RequestがAjaxかつPOSTでなければBadRequestHttpExceptionを発生させる. * * @param Application $app * @param Request $request * * @return \Symfony\Component\HttpFoundation\JsonResponse */ public function fcommit(Application $app, Request $request) { log_info('test OK', array('sendId' => ""null"")); // タイムアウトしないようにする set_time_limit(0); // デフォルトの設定ではメールをスプールしてからレスポンス後にメールを一括で送信する。 // レスポンス後に一括送信した場合、メールのエラーをハンドリングできないのでスプールしないように設定。 $app['swiftmailer.use_spool'] = false; $qb = $app['orm.em']->createQueryBuilder(); $qb->select('s') ->from(""\Plugin\MailMagazine\Entity\MailMagazineSendHistory"", 's') ->where('s.end_date is null and s.send >= :nw and s.send < :nw5 ') ->setParameter(""nw"", date(""Y-m-d H:i:00"")) ->setParameter(""nw5"", date(""Y-m-d H:i:00"", strtotime(""+5 minute""))); $query = $qb->getQuery(); $customers = $query->getResult(); if ( count($customers) > 0 ){ $service = $this->getMailMagazineService($app); foreach($customers as $c){ $id = $c->getId(); log_info('メルマガ配信自動処理開始', array('id' => $id)); /** @var MailMagazineSendHistory $sendHistory */ $sendHistory = $service->sendrMailMagazine($id, 0, 10000000); if ($sendHistory->isComplete()) { $service->sendMailMagazineCompleateReportMail(); } log_info('メルマガ配信自動処理完了', array('id' => $id)); } } else{ log_info('送信対象がありません'); } return $app->json(array('Success' => 'ok')); } |
8.インターフェース(入口)を作る
メルマガは管理側の機能のため、直前に呼び出ししますと、認証エラーが発生し、せっかく作った処理は使えなくなります。
使えるために、フロント側のインターフェースを用意し、そこから呼び出せば、認証エラーの問題を解決します。
「MailMagazine\ServiceProvider\MailMagazineServiceProvider.php」ファイル(160行あたり)に下記を追加し、穴を開けてフロント側から呼び出せるように対応します。
ここで、「/plugin/mail_magazine/fcommit」URLを定義しました。フロント側からこのURLを手動で叩いたら、過去直近5分以内に指定した配信日時のメルマガを配信します。
1 2 3 4 5 6 7 8 9 10 11 12 |
/*** フロントのルート追加 ***/ $front = $app['controllers_factory']; $front->match('/plugin/mail_magazine/fcommit', '\\Plugin\\MailMagazine\\Controller\\MailMagazineController::fcommit') ->bind('plugin_mail_magazine_fcommit'); // mount controllers $app->mount('/', $front); |
9.繋ぎ
crontabからcurlを使って、直接ステップ8で設定したURLを呼び出すことが可能ですが、ここで、ワンクッションを挟んで、crontabとURLの繋ぎを作ります。
public_htmlなどルートディレクトリの直下に、「fcommit.php」ファイルを作って、下記の内容を新規作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?php $url = ""https://bijoux.la/plugin/mail_magazine/fcommit; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $html = curl_exec($ch); curl_close($ch); //終了 |
自動配信のため、サーバーにログインし、Crontabを編集し、一定の間隔をおいて、メルマガ配信日時指定(予約配信)機能(上記の「fcommit.php」)を呼び出します。
ここでxserverを例として、説明します。
サーバーパネルから、Cron設定→Cron設定追加の順で、Cron設定画面を開きます。下図のように、設定します。
5分ごと1回に自動配信なので、分のところに「*/5」を入力し、ほかのところは「*」を入力します。
コマンド欄に「/usr/bin/php /home/xxxx/xiyuan.jp/public_html/fcommit.php 」(実際の環境に合わせて、読み替えてください)を入力し、確認画面に進んで、完了させます。
10.まとめ
以上のステップで、eccube3 メルマガプラグインの配信日時指定(予約配信)機能を完了しました。いかがでしょうか。考え方を思いつけば、既存の即時配信処理を真似し、少し加えたら、メルマガ配信日時指定(予約配信)機能を完成できます。読者の皆様はご自身の環境に合わせて作ってみましょうか。配信日時のUI操作性などいくつかの改善点があるかと思いますが、この実装をベースにして、より良い機能を実装しましょう。