ECCUBEでのフォームカスタマイズ方法
ECCUBEでは、FormTypeのカスタマイズをすると
フォームに項目が追加できる仕組みになっている
FormTypeカスタマイズではFormExtensionクラス
を使用するので下記で実装してく
FormExtensionクラスを作成する
- app/Customize/Form/Extension/ContactTypeExtension.phpを新規作成
<?php
namespace Customize\Form\Extension;
use Eccube\Form\Type\Front\ContactType;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Customize\Service\FileUploader;
class ContactTypeExtension extends AbstractTypeExtension
{
/**
* @var FileUploader
*/
private $fileUploader;
/**
* @var UrlGeneratorInterface
*/
private $urlGenerator;
public function __construct(FileUploader $fileUploader, UrlGeneratorInterface $urlGenerator) {
$this->fileUploader = $fileUploader;
$this->urlGenerator = $urlGenerator;
}
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
// ここでformビルダーに添付ファイル項目を追加 (input[type=file])
$builder->add('attachment', FileType::class, [
'label' => '添付ファイル',
'required' => false,
])
// ファイルの場所を保持するhidden項目も追加
->add('filename', HiddenType::class);
/**
* SUBMIT前にファイルをアップロードしてfilenameにセットする
*/
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event){
$data = $event->getData();
// ファイルが選択されている場合
if (!empty($data['attachment'])) {
// ファイルをアップロード
$filename = $this->fileUploader->upload($data['attachment']);
$data['filename'] = $this->urlGenerator->generate('homepage', [], true) . $filename;
unset($data['attachment']);
// アップロードしたデータを保存
$event->setData($data);
}
});
}
/**
* {@inheritdoc}
*/
public static function getExtendedTypes(): iterable
{
yield ContactType::class;
}
}
EC-CUBE 4.0では、getExtendedType
関数が必須、
EC-CUBE 4.1以降は、getExtendedType
関数が必須なので注意
public function getExtendedType()
{
return ContactType::class;
}
public static function getExtendedTypes(): iterable
{
yield ContactType::class;
}
FileUploaderクラスを作成する
- 順番が前後したけど、上記で作成した
ContactTypeExtension
で使用しているCustomize\Service\FileUploader を新規作成
<?php
namespace Customize\Service;
use Eccube\Common\EccubeConfig;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class FileUploader
{
/**
* @var EccubeConfig
*/
private $eccubeConfig;
public function __construct(EccubeConfig $eccubeConfig) {
$this->eccubeConfig = $eccubeConfig;
}
/**
* ファイルをアップロードする
**/
public function upload(UploadedFile $file)
{
$filename = date('mdHis') . uniqid('_') . '.' . $file->guessExtension();
$file->move(
$this->eccubeConfig["eccube_save_image_dir"]. '/contact',
$filename
);
return "contact/$filename";
}
}
MailServiceクラスを作成する
今回、メール送信時にファイル添付を行うため、既存の送信処理を改修する必要がある
そのため既存のMailService::sendContactMail
を下記手順でオーバーロードする
- app/Customize/Service/MailService.php を新規作成
<?php
namespace Customize\Service;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
class MailService extends \Eccube\Service\MailService
{
/**
* Send contact mail.
*
* @param $formData お問い合わせ内容
*/
public function sendContactMail($formData)
{
log_info('お問い合わせ受付メール送信開始');
$MailTemplate = $this->mailTemplateRepository->find($this->eccubeConfig['eccube_contact_mail_template_id']);
$body = $this->twig->render($MailTemplate->getFileName(), [
'data' => $formData,
'BaseInfo' => $this->BaseInfo,
]);
// 問い合わせ者にメール送信
$message = (new Email())
->subject('['.$this->BaseInfo->getShopName().'] '.$MailTemplate->getMailSubject())
->from(new Address($this->BaseInfo->getEmail02(), $this->BaseInfo->getShopName()))
->to($this->convertRFCViolatingEmail($formData['email']))
->bcc($this->BaseInfo->getEmail02())
->replyTo($this->BaseInfo->getEmail02())
->returnPath($this->BaseInfo->getEmail04());
// ⭐️追加:ファイル添付
if (!empty($formData['filename'])) {
$message->attachFromPath($this->eccubeConfig["eccube_save_image_dir"]. '/'. $formData['filename']);
}
// HTMLテンプレートが存在する場合
$htmlFileName = $this->getHtmlTemplate($MailTemplate->getFileName());
if (!is_null($htmlFileName)) {
$htmlBody = $this->twig->render($htmlFileName, [
'data' => $formData,
'BaseInfo' => $this->BaseInfo,
]);
$message
->text($body)
->html($htmlBody);
} else {
$message->text($body);
}
$event = new EventArgs(
[
'message' => $message,
'formData' => $formData,
'BaseInfo' => $this->BaseInfo,
],
null
);
$this->eventDispatcher->dispatch($event, EccubeEvents::MAIL_CONTACT);
try {
$this->mailer->send($message);
log_info('お問い合わせ受付メール送信完了');
} catch (TransportExceptionInterface $e) {
log_critical($e->getMessage());
}
}
}
既存のsrc/Eccube/Service/MailService::sendContactMail
をコピーして、
そこにファイル添付処理を追加してるだけ
あとはnamespace
とかextends
の部分を変更してる
app/Customize/Resource/config/services.yaml
を新規作成
services:
Customize\Service\MailService:
public: false
autowire: true
decorates: Eccube\Service\MailService
これにより既存のMailServiceよりも今回作成したMailServiceが優先されるようになる
添付ファイル項目を表示するためtwigを編集
app/template/{テーマ}/Contact/index.twig
を編集
ない場合はsrc/Eccube/Resource/template/{テーマ}/Contact/index.twig
をコピーして新規作成する
長くなるので追加箇所だけ記載する
<!-- ⭐️ 既存のformタグにenctype="multipart/form-data" を追加 -->
<form method="post" action="{{ url('contact') }}" class="h-adr" enctype="multipart/form-data" novalidate>
<!-- ⭐️ 添付ファイル項目を追加 -->
<dl>
<dt>
{{ form_label(form.attachment, '添付ファイル', { 'label_attr': { 'class': 'ec-label' }}) }}
</dt>
<dd>
<div class="ec-input{{ has_errors(form.attachment) ? ' error' }}">
{{ form_widget(form.attachment) }}
{{ form_errors(form.attachment) }}
{{ form_widget(form.filename) }}
</div>
{% if form.filename.vars.data != '' %}
<img src="{{ asset(form.filename.vars.data, 'save_image') }}" style="width: 150px !important;" />
{% endif %}
</dd>
</dl>
app/template/{テーマ}/Contact/config.twig
を編集
ない場合はsrc/Eccube/Resource/template/{テーマ}/Contact/config.twig
をコピーして新規作成する
長くなるので追加箇所だけ記載する
<!-- ⭐️ 添付ファイル項目を追加 -->
{% if form.filename.vars.data != '' %}
<dl>
<dt>
{{ form_label(form.filename, '添付ファイル', { 'label_attr': { 'class': 'ec-label' }}) }}
</dt>
<dd>
<img src="{{ asset(form.filename.vars.data, 'save_image') }}" style="width: 150px !important;" />
{{ form_widget(form.filename, { type : 'hidden' }) }}
</dd>
</dl>
{% endif %}
これで最後にキャッシュ管理からキャッシュ削除すれば完成
補足
ContactTypeExtension
の下記箇所で
ファイルのアップロード & ファイル名の設定をしている
/**
* SUBMIT前にファイルをアップロードしてfilenameにセットする
*/
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event){
$data = $event->getData();
if (!empty($data['attachment'])) {
$filename = $this->fileUploader->upload($data['attachment']);
$data['filename'] = $this->urlGenerator->generate('homepage', [], true) . $filename;
unset($data['attachment']);
$event->setData($data);
}
});
問い合わせはテーブルがない (=Entityを使用しない)ので、
ゲッター・セッターは使用せずに、PRE_SUBMIT
イベントで
新しいデータを $event->setData($data);
でセットする
ECCUBE4にて、お問い合わせフォームに添付ファイルを追加した
合わせてメール送信もファイルを添付するように改修を行う