[EC-CUBE 4]問い合わせフォームの複製

EC-Cube4.xは問い合わせフォームが一つしか実装されていない。
もう一つフォームを実装する場合の方法。

今回は、「app/Customize/」にコードを作成して、
新たに「http://〇〇○.△△△/contact2」にデフォルトと同じ問い合わせフォームを作成してみる。
また、問い合わせメールの送信時や問い合わせ画面表示時などのアクションは使用しない。

問い合わせページのテンプレートを複製

デフォルトの問い合わせフォームのテンプレートは、
「src/Eccube/Resource/template/default/Contact/index.twig」(入力画面)、
「src/Eccube/Resource/template/default/Contact/confirm.twig」(確認画面)と、
「src/Eccube/Resource/template/default/Contact/complete.twig」(完了画面)。

これらを「app/template/default/Contact2/index.twig 」、
「app/template/default/Contact2/confirm.twig 」 、
「app/template/default/Contact2/complete.twig 」にコピーする

ただし、formタグのactionがcontactになっているので、index.twigとconfirm.twigは修正が必要。

    <div class="ec-contactRole">
        <div class="ec-pageHeader">
            <h1>{{ 'お問い合わせ'|trans }}</h1>
        </div>
        <div class="ec-off1Grid">
            <div class="ec-off1Grid__cell">
                <form method="post" action="{{ url('contact2') }}" class="h-adr" novalidate>
                    <span class="p-country-name" style="display:none;">Japan</span>
                    {{ form_widget(form._token) }}
    <div class="ec-contactConfirmRole">
        <div class="ec-pageHeader">
            <h1>{{ 'お問い合わせ'|trans }}</h1>
        </div>
        <div class="ec-off1Grid">
            <div class="ec-off1Grid__cell">
                <form method="post" action="{{ url('contact2') }}" class="h-adr">
                    {{ form_widget(form._token) }}

complete.twigはそのままコピーする。

送信メールのテンプレートを複製する

デフォルトの送信メールのテンプレートは、
「src/Eccube/Resource/template/default/Mail/contact_mail.twig」(テキストメール版)と、
「src/Eccube/Resource/template/default/Mail/contact_mail.html.twig」(HTMLメール版) 。

これらを「app/template/default/Mail/contact2_mail.twig」と、
「app/template/default/Mail/contact2_mail.html.twig」にコピー 。

送信メールのテンプレートをデータベースに登録する

「dtb_mail_template」に先程コピーしたテンプレートを登録する。

INSERT INTO `dtb_mail_template`
 (`creator_id`, `name`, `file_name`, `mail_subject`, `create_date`, `update_date`, `discriminator_type`) VALUES
 (
    NULL,
    '問合受付メール', /* 管理画面に表示されるテンプレート名 */
    'Mail/contact2_mail.twig', /* テンプレートの場所 */
    'お問い合わせを受け付けました。', /* メールのタイトル */
    NOW(),
    NOW(),
    'mailtemplate'
);

メールサービスをカスタマイズする

作成したテンプレートを使用してメールを送る場合は、MailServiceで指定する。
デフォルトのMailServiceは「src/Eccube/Service/MailService.php」にあるので、
「app/Customize/Service/MailService.php」を作成して、MailServiceを拡張する。

追加するクラスメソッドは「sendContactMail」を参考に、今回は必要な部分だけを変更する。

<?php

/*
 * This file is part of EC-CUBE
 *
 * Copyright(c) LOCKON CO.,LTD. All Rights Reserved.
 *
 * http://www.lockon.co.jp/
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Customize\Service;

use Eccube\Common\EccubeConfig;
use Eccube\Entity\BaseInfo;
use Eccube\Entity\Customer;
use Eccube\Entity\MailHistory;
use Eccube\Entity\MailTemplate;
use Eccube\Entity\Order;
use Eccube\Entity\OrderItem;
use Eccube\Entity\Shipping;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Eccube\Repository\BaseInfoRepository;
use Eccube\Repository\MailHistoryRepository;
use Eccube\Repository\MailTemplateRepository;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Eccube\Service as Service;

class MailService extends Service\MailService
{
    /**
     * Send contact mail.
     *
     * @param $formData お問い合わせ内容
     */
    public function sendContact2Mail($formData)
    {
        log_info('お問い合わせ2受付メール送信開始');

        // $MailTemplate = $this->mailTemplateRepository->find($this->eccubeConfig['eccube_contact2_mail_template_id']);
        // テンプレートを指定。テンプレートをデータベースに登録した時に作成された「id」を直接指定
        $MailTemplate = $this->mailTemplateRepository->find(9);

        $body = $this->twig->render($MailTemplate->getFileName(), [
            'data' => $formData,
            'BaseInfo' => $this->BaseInfo,
        ]);

        // 問い合わせ者にメール送信
        $message = (new \Swift_Message())
            ->setSubject('['.$this->BaseInfo->getShopName().'] '.$MailTemplate->getMailSubject())
            ->setFrom([$this->BaseInfo->getEmail02() => $this->BaseInfo->getShopName()])
            ->setTo([$formData['email']])
            ->setBcc($this->BaseInfo->getEmail02())
            ->setReplyTo($this->BaseInfo->getEmail02())
            ->setReturnPath($this->BaseInfo->getEmail04());

        // HTMLテンプレートが存在する場合
        $htmlFileName = $this->getHtmlTemplate($MailTemplate->getFileName());
        if (!is_null($htmlFileName)) {
            $htmlBody = $this->twig->render($htmlFileName, [
                'data' => $formData,
                'BaseInfo' => $this->BaseInfo,
            ]);

            $message
                ->setContentType('text/plain; charset=UTF-8')
                ->setBody($body, 'text/plain')
                ->addPart($htmlBody, 'text/html');
        } else {
            $message->setBody($body);
        }

        // 今回はイベントを発生させないようにする。
        // $event = new EventArgs(
        //     [
        //         'message' => $message,
        //         'formData' => $formData,
        //         'BaseInfo' => $this->BaseInfo,
        //     ],
        //     null
        // );
        // $this->eventDispatcher->dispatch(EccubeEvents::MAIL_CONTACT, $event);

        $count = $this->mailer->send($message);

        log_info('お問い合わせ受付メール送信完了', ['count' => $count]);

        return $count;
    }
}

コントローラを追加する

実際に問い合わせを処理するコントローラを作成する。
今回は、フォームや処理の内容は、デフォルトの「問い合わせフォーム」と同じでいいので、
「app/Customize/Controller/Contact2Controller.php」を作成し、
デフォルトの「src/Eccube/Controller/ContactController.php」の内容をベースに最低限の修正のみ行う。

<?php

/*
 * This file is part of EC-CUBE
 *
 * Copyright(c) LOCKON CO.,LTD. All Rights Reserved.
 *
 * http://www.lockon.co.jp/
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Customize\Controller;

use Eccube\Controller\AbstractController;
use Eccube\Entity\Customer;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Eccube\Form\Type\Front\ContactType;
use Customize\Service\MailService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

class Contact2Controller extends AbstractController
{
    /**
     * @var MailService
     */
    protected $mailService;

    /**
     * ContactController constructor.
     *
     * @param MailService $mailService
     */
    public function __construct(
        MailService $mailService)
    {
        $this->mailService = $mailService;
    }

    /**
     * お問い合わせ画面.
     *
     * @Route("/contact2", name="contact2")
     * @Template("Contact2/index.twig")
     */
    public function index(Request $request)
    {
        $builder = $this->formFactory->createBuilder(ContactType::class);

        if ($this->isGranted('ROLE_USER')) {
            /** @var Customer $user */
            $user = $this->getUser();
            $builder->setData(
                [
                    'name01' => $user->getName01(),
                    'name02' => $user->getName02(),
                    'kana01' => $user->getKana01(),
                    'kana02' => $user->getKana02(),
                    'postal_code' => $user->getPostalCode(),
                    'pref' => $user->getPref(),
                    'addr01' => $user->getAddr01(),
                    'addr02' => $user->getAddr02(),
                    'phone_number' => $user->getPhoneNumber(),
                    'email' => $user->getEmail(),
                ]
            );
        }

        // FRONT_CONTACT_INDEX_INITIALIZE
        // 今回はイベントを発生させないようにする。
        // $event = new EventArgs(
        //     [
        //         'builder' => $builder,
        //     ],
        //     $request
        // );
        // $this->eventDispatcher->dispatch(EccubeEvents::FRONT_CONTACT_INDEX_INITIALIZE, $event);

        $form = $builder->getForm();
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            switch ($request->get('mode')) {
                case 'confirm':
                    $form = $builder->getForm();
                    $form->handleRequest($request);

                    return $this->render('Contact2/confirm.twig', [
                        'form' => $form->createView(),
                    ]);

                case 'complete':

                    $data = $form->getData();

                    $event = new EventArgs(
                        [
                            'form' => $form,
                            'data' => $data,
                        ],
                        $request
                    );
                    // 今回はイベントを発生させないようにする。
                    // $this->eventDispatcher->dispatch(EccubeEvents::FRONT_CONTACT_INDEX_COMPLETE, $event);

                    $data = $event->getArgument('data');

                    // メール送信
                    $this->mailService->sendContact2Mail($data);

                    return $this->redirect($this->generateUrl('contact2_complete'));
            }
        }

        return [
            'form' => $form->createView(),
        ];
    }

    /**
     * お問い合わせ完了画面.
     *
     * @Route("/contact2/complete", name="contact2_complete")
     * @Template("Contact2/complete.twig")
     */
    public function complete()
    {
        return [];
    }
}

dtb_pageにページを登録する

コンテンツ管理からアクセスできるようにデータを登録する。

INSERT INTO `dtb_page` (`master_page_id`, `page_name`, `url`, `file_name`, `edit_type`, `author`, `description`, `keyword`, `create_date`, `update_date`, `meta_robots`, `meta_tags`, `discriminator_type`) VALUES
(
    NULL,
    'お問い合わせ2(入力ページ)', /* ページ名 */
    'contact2', /* url */
    'Contact2/index', /* テンプレートファイル */
    2,
    NULL,
    NULL,
    NULL,
    NOW(),
    NOW(),
    NULL,
    NULL,
    'page'
),(
    NULL,
    'お問い合わせ2(完了ページ)', /* ページ名 */
    'contact2_complete', /* url */
    'Contact2/complete', /* テンプレートファイル */
    2,
    NULL,
    NULL,
    NULL,
    NOW(),
    NOW(),
    NULL,
    NULL,
    'page'
);

キャッシュをクリア

今の状態だと、キャッシュの関係でなのか、アクセスができない。

「/var/cache/prod」フォルダを空っぽにして、再度キャッシュを作成するようにすれば、アクセスできるようになります。

コンテンツ管理ページで設定を行う

最後に、「管理画面」→「コンテンツ管理」→「ページ管理」にアクセスして、
ページの設定を行う。

最後に

今回のようにフォームの内容が同じものを複数作るということはないと思うので、
必要に応じてフォームをカスタマイズする必要があると思うが、
これは、通常のフォームのカスタマイズのように行えばいい、、、と思う。

コメント

  1. haga

    エラーになってしまいました。何が問題なのかわかりません。もしお解りになられるようでしたらアドバイスお願いします。
    Whoops, looks like something went wrong.

    (2/2) FileLoaderLoadException
    The autoloader expected class “Customize\Controller\Contact2Controller” to be defined in file “/***************/vendor/composer/../../app/Customize/Controller/Contact2Controller.php”. The file was found but the class was not in it, the class name or namespace probably has a typo in /*******************/app/config/eccube/services.yaml (which is loaded in resource “/*******************/app/config/eccube/services.yaml”).

    (1/2) RuntimeException
    The autoloader expected class “Customize\Controller\Contact2Controller” to be defined in file “/*******************/vendor/composer/../../app/Customize/Controller/Contact2Controller.php”. The file was found but the class was not in it, the class name or namespace probably has a typo.

    • エラーを見ると、
      「The file was found but the class was not in it, the class name or namespace probably has a typo.」という記載があります。
      これは、「、、、app/Customize/Controller/Contact2Controller.php」というファイルは存在するけれど、
      その中に「Contact2Controller」というクラスが見つかりません。クラス名かnamespaceが打ち間違いかもしれません。
      というエラーですので、
      一度、「、、、app/Customize/Controller/Contact2Controller.php」ファイル内のクラス名を確認してみてください。

      ちなみに、ファイル名とクラス名は合わせる必要があるので、
      もし、クラス名を変更したい場合は、ファイル名もそれに合わせる必要があります。

      • haga

        ありがとうございました!!!
        素晴らしい!!!
        正におっしゃる通りで、namespaceが打ち間違いでした!
        自分はもう少ししっかり見直すべきでした!お恥ずかしい限りです。
        お手数おかけして申し訳ありませんでした。。。

        たった今、2つ目のお問い合わせのフォームが出来上がりました!

        本当にありがたいです。
        このページ、最高に助かりました!

        • haga

          実践して、少し見つけましたので、せっかくなので記しておきます。

          ★送信メールのテンプレートをデータベースに登録する
          ※NOW{}になってました。

          INSERT INTO “dtb_mail_template”
          (“creator_id”, “name”, “file_name”, “mail_subject”, “create_date”, “update_date”, “discriminator_type”) VALUES
          (
          NULL,
          ‘パソコン宅急便「集荷の依頼」受付メール’, /* 管理画面に表示されるテンプレート名 */
          ‘Mail/contact2_mail.twig’, /* テンプレートの場所 */
          ‘パソコン宅急便「集荷の依頼」を受け付けました。’, /* メールのタイトル */
          NOW(),
          NOW(),
          ‘mailtemplate’
          );

          ★app/template/default/Contact2/confirm.twig
          ※contact2
          22

        • いえいえ、打ち間違いは自分ではなかなか見つけることが難しいものだと思うので仕方ないと思いますよ。
          とにかく問題が解決したようで良かったです!

  2. 通りすがりのニート

    コメント失礼します。
    確認ボタンを押しても確認画面に推移しない場合、何が原因と考えられるでしょうか。
    全て御指南通りにできていると思いますので、何が悪いのかわかりません。
    よろしければご教授いただけると嬉しいです。

    よろしくお願いします。

    • コメントありがとうございます。
      先ほど、念のため最新版(4.2.2)でも動作するかを確認しましたが問題ありませんでした。
      一般的に、うまく遷移できない場合、
      ・Javascriptでエラーが発生している。
      ・URLが間違っている。
      ・サーバー側でエラーが発生している。
      ・サーバー側でルーティングやテンプレートの指定などが間違っている。
      が考えられるかと思います。
      また、すでにカスタマイズされていたり、プラグインがインストールされている場合、
      それに準じたカスタマイズが別途必要となる場合もあります。
      ブラウザ側やサーバー側のエラーログなどを確認していただき、
      どこでエラーが発生しているのか、エラーが発生していない場合は、どこで誤った動作をしてしまっているのかを確認いただければと思います。

  3. 通りすがりのニート

    ご返信ありがとうございます。

    一度全部削除、キャッシュも全部削除してからやってみると動作しました。
    お早い回答、ご教授いただきありがとうございました。

    この流れで問い合わせ項目の追加・変更も実行してみたのですが、ContactType.php、Contact2Controller.php、各Twigに記述するだけでは正常に動かず項目の追加でエラーが頻発してしまいました。ECCUBE4.2からSymphonyの仕組みが変わったとの情報がありましたがそこまで大きく変わったのでしょうか?

    もしこちらも検証いただけましたら嬉しいです。
    応援しています。今度とも頑張ってください。

    • そうですか、動作したようでよかったです。

      確かに、ec-cubeは4.0はSymfony3.4、4.1はSymfony4.4、4.2はSymfony5.4とSymfonyのメジャーバージョンが変わってしまうので、いろいろと厄介ではあると思います。
      ただ、開発者向けの公式ドキュメントにマイグレーションについて解説があるので、そちらを参考にされたらいいかもしれませんね。
      4.0->4.1 https://doc4.ec-cube.net/update-40-41
      4.1->4.2 https://doc4.ec-cube.net/update-41-42

      応援ありがとうございます!
      最近全然更新しておりませんが、、、少しずつ、、、。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

*