1.はじめに
EcCube4でメールテンプレートを追加したいのに、プラグインなしでは難しそう…と感じていませんか。
受注確認メールを、支払い方法に応じて口座情報などを出し分けたい!
実は、正しい手順を押さえれば非常にシンプルな実装が可能です。
本記事では、実際にかかる手順(twig作成からDB登録、yaml設定まで)を4ステップで紹介します。
公式仕様やSymfony(ベースフレームワーク)のポイントも押さえ、保守性と拡張性などを損なわないことが大切です。
依存を避け、バージョンアップや長期運用に耐える仕組みを構築しましょう。
こんな方におすすめ
- EcCube4のカスタマイズに詳しくない
- インストール版のEcCubeを使っている
- 今後のカスタマイズの知識を養いたい
- データベースやウェブの基本知識はある
1-1. 本記事のゴールと想定読者
本記事ではEcCube4でのメールテンプレート追加方法を解説します
プラグインを使わずに実装したい方が対象です。
開発経験が浅くても理解できる構成にしました。
1-2. プラグインを使わない方法を選ぶメリット・デメリット
外部依存を減らし保守性を高められるのが利点です。
更新時の互換性リスクを抑えられる強みもあります。
余計な変更がなくバージョン管理しやすいです。
一方で、作業量や知識負担は増える傾向にあります。
1-3. 作業前に知っておくべきEcCube4のメール送信仕様
標準では機能ごとに1種類のメールのみ送信可能です。
テンプレート追加にはDBと設定の変更が必要となります。
送信処理はSymfonyの仕組みを利用しています。
2. メールテンプレート追加の全体像
2-1. 実装フローの概要(4ステップ)
twig作成→DB登録→yaml調整→ID設定の順序です。
初回のみ型の配列化と、DB呼び出し部分のカスタマイズが必要となります。
全体像を把握してから作業を始めると効率的です。
2-2. 必要な環境・事前準備(開発環境、DBアクセス権限など)
安全のため、ローカルに開発環境を用意します。
エディタはtwigとyaml編集に対応していること(VSCodeなど)が望ましいです。
環境によっては、バックアップ取得も忘れずに行いましょう。
3. ステップ1:メール本文テンプレート(twig)の追加
3-1. twigファイルの配置場所と命名規則
DBから確認できる、既存メールテンプレートと同じディレクトリに配置します。
※場合によっては、サブディレクトリも可。
命名は用途が分かる短い英語名が望ましいです。
拡張子は必ず.twigとしてください。
4-4サンプル例で言うと「order_custom.twig」
3-2. テンプレート作成の手引き
変数の使い方や構造は既存ファイルを参考にします。
特にテキストメールは、テンプレートの改行やスペースが本文に反映されます。
改行やインデントに統一感を持たせ、違和感のないように注意しましょう。
Orderの例なら「order.twig/order_html.twig」をコピーして書き換える
3-3. レイアウトや変数の利用方法
注文情報や会員情報は変数で埋め込みます。
変数名はコントローラー側で用意されたものを使います。
表示形式はtwigのフィルタで整形可能です。
注意
メールテンプレートを選択するにあたり、変数を使う場合は慎重に扱いましょう。
未定義の変数にアクセスした場合など、エラーの発生要因になります。
if分による存在チェックも有効です。
4. ステップ2:データベースにテンプレート情報を登録
4-1. メールテンプレート管理テーブルの構造
テーブルには編集項目としてID、表示名、件名、ファイルパスがあります。
コピー元が正しければテーブルの種別(descrimitor_type)は保持される設計です。
構造を理解してから登録作業を行います。
4-2. 名前とtwigファイルパスの設定方法
DBのGUI編集ツールで複製して編集します。
パスは編集元からtwigのファイル名のみ変更してください。
Docker環境などPHPMyAdminがなくても、Adminerを使えばPHP上で動作します。
↓少し古いバージョン、Docker版EcCube4.2にて。
4-3. 既存メールとの重複を避けるための注意点
名称やパスが既存と同じだとバグがでる可能性があります。
管理画面を通していないため、DB構造上の不備がなければ登録までは通ってしまいます。
作成日時などは動作に影響しませんが、カレンダーがあれば現在日時にしておきましょう。
4-4. データベースの設定サンプル
Adminerのキャプチャを使ったデータベースの設定サンプルを添付します。
画像の「name」、「file_name」、「mail_subject」が変更箇所です。
作成後は、「id」項目を控えておいてください。
ステップ3:【初回のみ】yamlファイルの型を配列化&メール呼び出しのカスタマイズ
5-1. yamlファイルの配列化
5-1-1. なぜ型を配列化する必要があるのか
デフォルトではDB上にあるメールテンプレートのIDを指定します。
つまり、単一ファイルしか想定していません。
型を整数型から配列型に変更し、複数選択が可能な形式に変換します。
5-1-2. yamlファイルの編集手順と書き方
設定ファイルは「app/config/eccube/packages/eccube.yaml」にあります。
今回は直接書く構想ですが、バージョンアップで上書きされる個所です。
Gitなどのバージョン管理は忘れずにしておきましょう。
5-1-3. カスタマイズファイルの配置場所と命名ルール
app/Customize配下に配置するのが基本です。
今回は面倒なyamlは直書きにし自動で読まれるコントローラーは仕様に準拠します。
命名は役割が分かる短い英語名にしましょう。
EcCube(Symfony)からも外れないほうが良いと思います。
5-1-4. yamlファイルの配列化
まずは、シンプルに設定値を配列化します。
ステップ4とまとめても構いませんが、初回だけなのでここだけ取り出しました。
# app/config/eccube/packages/eccube.yaml
# この行をコメントアウト→eccube_order_mail_template_id: 1
# 以下のように配列化した設定値を追加(上のものを[]でくくっても可)
eccube_order_mail_template_ids: [1]
5-2. メール呼び出しのカスタマイズ
メール呼び出しとは、注文詳細からのオーダーメールを想定しています。
自動返信メールの場合は、コントローラーの編集でより複雑です。
想定ケースは、自動返信メールの後に手動で顧客に注文確認メールを送る際になります。
5-2-1. カスタマイズのルール
原則はappディレクトリを使っていきます。
コントローラーやFormまわりはapp\Customizeで問題ないでしょう。
こちらはSymfonyではなくEcCubeのルールです。
https://doc4.ec-cube.net/customize_formtype
5-2-2. 設定ファイルへの記述サンプル
サンプルのファイル名とクラス名は任意です。
ディレクトリを変えても動作はします。
ただし、AutoLoadの仕様で名前とクラスは揃えましょう。
useやnamespace、yieldまわりを調整すれば他の型にも概ね転用可能です。
# app/Customize/Form/Type/Admin/OrderMailTypeExtension.php
元ファイル: src/Eccube/Form/Type/Admin/OrderMailType.php
<?php
namespace Customize\Form\Type\Admin;
use Eccube\Form\Type\Admin\OrderMailType;
use Doctrine\ORM\EntityRepository;
use Eccube\Common\EccubeConfig;
use Eccube\Form\Type\Master\MailTemplateType;
use Eccube\Form\Validator\TwigLint;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints as Assert;
class OrderMailTypeExtension extends AbstractTypeExtension
{
/**
* @var EccubeConfig
*/
protected $eccubeConfig;
/**
* MailType constructor.
*
* @param EccubeConfig $eccubeConfig
*/
public function __construct(
EccubeConfig $eccubeConfig
) {
$this->eccubeConfig = $eccubeConfig;
}
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('template', MailTemplateType::class, [
'required' => false,
'mapped' => false,
'query_builder' => function (EntityRepository $er) {
$qb = $er->createQueryBuilder('mt');
return $qb->andWhere($qb->expr()->in('mt.id', ':ids'))
->setParameter('ids', $this->eccubeConfig['eccube_order_mail_group_ids'])
->orderBy('mt.id', 'ASC');
},
])
->add('mail_subject', TextType::class, [
'required' => true,
'constraints' => [
new Assert\NotBlank(),
],
])
->add('tpl_data', TextareaType::class, [
'label' => false,
'mapped' => false,
'required' => false,
'constraints' => [
new TwigLint(),
],
])
;
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'admin_order_mail';
}
/**
* {@inheritdoc}
*/
public function getExtendedType()
{
return OrderMailType::class;
}
/**
* {@inheritdoc}
*/
public static function getExtendedTypes(): iterable
{
yield OrderMailType::class;
}
}
6. ステップ4:yamlファイルにメールIDを記述
6-1. メールIDの取得方法(DBからの確認手順)
DBのメールテンプレートテーブルを参照します。
「4-4」で言及した、自動生成されたDBのIDを確認してください。
このIDを「5-4」で変更したyamlに記述します。
配列形式になっていることを確認してください。
6-2. yamlへの反映方法
取得したIDを配列の要素として追加します。
ここでは、追加した「dtb_mail_template」のIDを10と想定します。
# app/config/eccube/packages/eccube.yaml
eccube_order_mail_template_ids: [1, 10]
IDに追加があれば、随時配列の中身を変えていきます。
ここも自動化を目指す場合は、ALTER TABLEでカテゴリーを追加する感じでしょうか。
色々やり方はあると思います(想定ケースがなく煮詰めてない)。
7. 実装時の注意点と拡張のヒント
7-1. なぜオーダーから一つしかメールを送れないのかを理解する
Eccubeの動作を見るときは、コントローラーがベースです(デバッグツールがあると分かりやすいです)。
PHPフレームワークである以上、どこかに記述があります。
ソースを読むなんて言いますが、全コードを読むなんて実質無理です。
処理のフローを掴んで、変える場所のアタリをつけるテクニックを身に着けましょう。
7-2. EccubeとSymfonyの関係を理解する
EccubeはSymfonyを拡張して作られたCMSです。
ベースとなるSymfonyバージョンもEccubeによって異なり、どのバージョンのドキュメントを見るかを間違えてはいけません。
今回はEccube4.2で作ったコードだったためSymfony5系でしたが、4.3系ではSymfonyは6系です。
はっきり言ってEccubeのドキュメントは情報がかなり欠けています。デフォルトとプラグイン以外の機能を使う場合はSymfonyが読めないと苦労するでしょう。
7-3-1. 具体的にどうやってドキュメントを見るのか
Eccubeのドキュメントを見てなければ、後はSymfonyを見に行きます。
何と言いますか、Eccubeのドキュメントに詳しい記載はありません(大体フォーラムがなんとかしている…)。
検索ワードの選定やアタリをつける場合に生成AIが役立ちます。
生成AI丸投げの場合はバージョンズレが頻発するので注意しましょう。
8. まとめ: オーダーメールを複数用意して手動作業をシステム化しよう
本記事では、EcCube4でプラグインを使わずにメールテンプレートを追加する具体的な手順を解説しました。
twigファイルの作成からデータベース登録、初回のみ必要なyaml配列化とカスタマイズ、メールID設定までを順序立てて説明し、公式仕様やSymfony準拠のポイントも押さえています。
これにより、外部依存を避けつつ長期運用に耐える柔軟なメール送信環境を構築できます。
振り込みや備考を使った処理の分岐は、ECサービスではしばしば発生するでしょう。
また、需給なのか無料プラグインが少なく相性次第でバグの原因にもなります。
簡単なものでしたら、自分で解決がおすすめです。
8-1. おまけ【発展】注文内容でメールを自動で振り分けたい時の処理フロー
まず、ここでは具体的なカスタマイズコードを示さないのでご了承ください。
あくまで、どこから手を付けていいかわからない時の為の参考です。
8-1-1. テンプレートからコントローラーを特定しよう
購入完了までは、カート処理→購入確認やら入力やら→確認→完了画面と遷移します。
この時、メールが送られるのはいつでしょうか?
フロー上は、確認→完了ですよね。確認画面へ行くたびにメール飛んだらもはやスパム。
Eccubeではコントローラーのコメントでデフォルトのtwigコントローラーを指定するので、そのファイルを探します。
アノテーション形式
ソースを眺めながら読んでください。そうでないと、全く何を言っているか分からないはずです。
8-1-2. 文字列検索で場所を推定する
カスタマイズ後のパスまたはデフォルト情報から、以下のファイルにたどり着きます。
src\Eccube\Resource\template\default\Shopping\confirm.twig
以上の結果から、コントローラーで「Shopping/confirm.twig」を呼んでいるコードを探せばいいとなります。
パスのバックスラッシュ「\」を「/」に置き換えて検索してください。
コントローラーとしては、恐らく1件しか見つからないと思います「src\Eccube\Controller\ShoppingController.php」。
8-1-3. コントローラーファイル内の関数を特定し処理を確認する
文字列検索でメソッドまで特定可能です(コメントでそのまま書いているので)。
コメントの方を呼んでいくと「 methods={“POST”}」もあり送信処理で呼ばれることも推測できます。
public function confirm(Request $request)
サラッと読んでいくと、注文チェックなどを行ってレスポンスを返すようになっています。
つまり、最終的な送信ではなく、まだ最低でも1STEPあるということですね。
returnやthrowが複雑で、結構癖のあるコードと思われます。
8-1-4. 実際に処理を行っているメソッドを特定し処理をもう一度確認する
上の項目でかなり近づきましたが、まだ正解ではありませんでした。
しかし、同じファイル内にはもう一つ同じテンプレートを使っているメソッドがあります。
public function checkout(Request $request)
confirmと似たような処理が続きます。
あらゆるエラー処理を抜け、すべてパス(通過)した場合に以下の記述にたどり着くでしょう。
$this->mailService->sendOrderMail($Order);]
ビンゴ!!
VSCodeあたりだと、「Ctrl」+「マウスクリック」でメソッド定義に飛べると思います。
src\Eccube\Service\MailService.php->sendOrderMail
上のメソッドをサービスとしてカスタマイズするか、大本のコントローラー側でメール処理を書き直します。
方法論としては前者が正しいですが、難易度的には後者のほうが楽です(サービスがコントローラーより面倒)。
いずれにしても、決済周りはプラグインも絡むので中々おすすめしづらいのが実情です。
8-2. Dispatchという選択肢
Symfonyの機能として、フックポイント(引っ掛ける=処理を差し込める隙間を作っておく)ことが可能です。
どんどん脱線している気がする。
例に上げた注文メールにも送信直前にポイントが設定してあるため、こちらを使って処理を調整することもできます。
フックかカスタマイズかは悩ましい。ここまでは実装していないので感想レベルだが、可能そうならフックでやるかな?という印象。
カスタマイズはフックと違い、メソッド単位で上書きするため余計な部分に干渉します。
可能な範囲で、小幅改修・小幅修正に留めるのがポイントです。
注意
久しぶりにカロリー高めなプログラム記事を書きました。
おまけの章は初心者の域を超えていると思います。
いずれ読めるようになると思うので、無理しない程度に流し見してみましょう。