# EC-CUBE4 お問い合わせフォームに添付ファイルを追加
EC-CUBE 4 では、Symfony の FormExtension の仕組みを使って、既存のフォームをカスタマイズできます。
EC-CUBE 4 開発者向けドキュメント FormType のカスタマイズ (opens new window)
Symfony のドキュメント (opens new window)
# 拡張方法
app/Customize/Form/Extension/ に AbstractTypeExtension を継承したクラスファイルを作成することで、自動的に FormExtension として認識されます。
# 拡張するフォーム種類の指定
EC-CUBE 4.1 以降は、getExtendedType 関数は必ず実装し、拡張するフォームの種類を指定する必要があります。
public static function getExtendedTypes(): iterable
{
yield EntryType::class;
}
# 拡張用の関数
以下の関数をオーバーライドし、引数で渡されるパラメータを変更することでフォームのカスタマイズが可能です。
buildForm()
buildView()
configureOptions()
finishView()
# 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']);
unset($data['attachment']);
// アップロードしたデータを保存
$event->setData($data);
}
});
}
/**
* {@inheritdoc}
*/
public static function getExtendedTypes(): iterable
{
yield ContactType::class;
}
}
# FileUploader クラスを作成する
app/Customize/Service/FileUploader.php 作成
<?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 クラスを作成
メール送信時にファイル添付を行うため、既存の送信処理を改修する必要があります。
そのため既存の src/Eccube/Service/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());
}
}
}
# カスタマイズ MailService 優先設定
app/Customize/Resource/config/services.yaml 作成
services:
Customize\Service\MailService:
public: false
autowire: true
decorates: Eccube\Service\MailService
既存の MailService よりも今回作成した MailService が優先されるように
# お問い合わせページに添付ファイル項目追加 twig 編集
app/template/default/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>
</dd>
</dl>
# お問い合わせ確認ページに添付ファイル項目追加 twig 編集
app/template/default/Contact/confirm.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: 100px;" />
{{ form_widget(form.filename, { type : 'hidden' }) }}
</dd>
</dl>
{% endif %}