# 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 %}
2023-04-29
  • ec-cube