注文ごとに独自の情報を持たせたい、というのはよくある要望です。EC-CUBEの注文情報は dtb_order テーブルに保存されますが、ここへ自分で決めた項目をひとつ足し、注文画面のフォームから保存できるようにするまでを通しで解説します。例として「領収書が必要/不要」のチェックボックスを設置します。
やることは3つです。①Orderエンティティを拡張して dtb_order に項目を追加、②OrderTypeを拡張して注文画面のフォームに項目を追加、③Twigテンプレートに表示用のコードを追記。
Controllerのカスタマイズは不要です。注文画面のフォームは、すでに既存のShoppingControllerからテンプレートへ渡されているためです。
つまずきやすいのは②。フォームの項目を無条件に追加してしまうと、注文完了の直前で入力値が消えます。理由は本文で解説します。
【動作環境】EC-CUBEのバージョン:4.2.1 / サーバー:Xserver
開発前にデバッグモードの設定をおすすめします。エラーが起きたときに詳細情報が表示されるようになり、原因の箇所を探しやすくなります。カスタマイズ後は解除を忘れずに。
設定と解除の手順は、こちらの記事にまとめています。
このカスタマイズでやること
作業は次の3つに分かれます。どのファイルを触るのかを先に押さえておくと、途中で迷いません。
- 1
dtb_orderテーブルに新規プロパティを追加(拡張)する - 2入力フォームを拡張(OrderTypeExtensionを作成)する
- 3Twigテンプレートにフォームと表示用のコードを追記する
| 手順 | 置き場所 | 役割 |
|---|---|---|
| 1 | app/Customize/Entity/OrderTrait.php |
注文情報に receipt という保存先を用意する |
| 2 | app/Customize/Form/Extension/OrderTypeExtension.php |
注文画面のフォームにチェックボックスを足す |
| 3 | app/template/default/Shopping/index.twigapp/template/default/Shopping/confirm.twig |
入力欄と、入力結果を画面に出す |
必要に応じて、注文受付メールや受注管理画面にも表示用のコードを追記します(本記事では割愛します)。
dtb_orderテーブルに新規プロパティを追加(拡張)する
まずは注文情報を保存しておくテーブル dtb_order に、独自のプロパティ receipt を追加します。EC-CUBEでは既存のエンティティをTraitで拡張することで、コアのファイルを書き換えずに項目を増やせます。
テーブルの拡張そのものについては、別記事で基本から解説しています。ここでは実際に作成したエンティティと操作だけを記します。
Orderエンティティを拡張する(OrderTraitの作成)
以下のTraitファイルを作成し、app/Customize/Entity 下に保存します。
<?php
namespace Customize\Entity;
use Doctrine\ORM\Mapping as ORM;
use Eccube\Annotation\EntityExtension;
/**
* @EntityExtension("Eccube\Entity\Order")
*/
trait OrderTrait
{
/**
* @var boolean
*
* @ORM\Column(name="receipt", type="boolean", nullable=false, options={"default": false})
*/
private $receipt = false;
/**
* Set receipt.
*
* @param boolean $receipt
*
* @return Order
*/
public function setReceipt($receipt = false)
{
$this->receipt = $receipt;
return $this;
}
/**
* Get receipt.
*
* @return boolean
*/
public function getReceipt()
{
return $this->receipt;
}
}
| 項目 | 内容 |
|---|---|
| プロパティ名 | receipt |
| 型 | boolean(真偽値) |
| 初期値 | false |
初期値を options={"default": false} で指定しているのがポイントです。すでに注文データが入っているテーブルであっても、既存の行に入れる値が決まるため、そのまま項目を足せます。
サーバーにSSH接続してテーブル拡張
Traitファイルをアップしたら、SSH接続して以下のコマンドを順に実行し、データベースを拡張します。Traitを置いただけではEC-CUBE側がプロパティを認識しないため、この3つはセットです。
-
STEP1Proxyを生成する
bin/console eccube:generate:proxiesTraitに書いた内容を、EC-CUBEがエンティティの一部として扱えるようにするための生成処理です。
-
STEP2キャッシュを削除する
bin/console cache:clear --no-warmup古い定義が残っていると、生成したProxyが読まれません。
-
STEP3データベースへ反映する
bin/console doctrine:schema:update --dump-sql --force実行されるSQLを表示したうえで、データベースへ反映します。問題なく終われば、
dtb_orderテーブルにreceiptというプロパティができているはずです。
XserverでのSSH接続の手順は、OSごとに記事を用意しています。
入力フォームを拡張(OrderTypeExtensionを作成)する
続いて、追加したプロパティ receipt に値をセットするためのフォームを、注文画面(/shopping)に設置します。
注文のためのフォームにはOrderTypeが用意されており、すでに注文画面でフォームが埋め込まれています。そこで、OrderTypeを拡張したOrderTypeExtensionを作成し、app/Customize/Form/Extension 下に保存します。
<?php
namespace Customize\Form\Extension;
use Eccube\Form\Type\Shopping\OrderType;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
class OrderTypeExtension extends AbstractTypeExtension
{
public static function getExtendedTypes(): iterable
{
return [OrderType::class];
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
if (!$options['skip_add_form']) {
$builder
->add('receipt', CheckboxType::class, [
'label' => '領収証が必要な方はチェックを入れてください。',
'required' => false,
'mapped' => true,
]);
}
}
}
この if (!$options['skip_add_form']) を外さないでください。外すと、注文完了の直前でチェックの内容が消えます。
EC-CUBEは確認画面から注文処理へ進むときに、フォームをもう一度組み立て直します。このときは skip_add_form を有効にしてフォーム項目の定義を意図的に飛ばし、すでにOrderへ入っている値をそのまま引き回す作りになっています。拡張側が無条件に項目を足してしまうと、この場面でも項目が復活し、送信されていない状態の値で上書きされてしまう、というわけです。
FormTypeの拡張と、チェックボックスなどのフォーム部品については、それぞれ別記事で詳しく解説しています。後者ではCheckboxTypeではなくChoiceTypeを使った実装方法を紹介しています。
FormExtensionを使ったFormTypeのカスタマイズ
ドロップダウンリスト / ラジオボタン / チェックボックスの実装方法
Twigテンプレートをカスタマイズする
作成したフォームを表示させるには、本来ならControllerからTwigテンプレートへフォームを渡す処理が必要です。ただし今回は、すでに既存のShoppingControllerからOrderTypeのフォームが渡されているため、Controllerのカスタマイズは不要です。
注文画面に対応するTwigテンプレート Shopping/index.twig を開き、チェックボックスを表示させたい箇所に以下を追記します。
{{ form_widget(form.receipt) }}
続いて、注文確認画面 Shopping/confirm.twig で、チェックに応じた内容を表示させます。適当な場所に以下を追記してください。
{{ Order.receipt ? '領収書:必要' : '領収書:不要' }}
入力画面と確認画面で、参照するものが違います。入力画面はフォームなので form.receipt、確認画面はフォームではなく注文そのものを表示しているので Order.receipt です。確認画面にはフォームが渡っていないため、ここで form_widget を書いても表示されません。
見た目は、好みに応じてレイアウトやスタイルを調整してください。
EC-CUBEでのCSSの当て方と反映方法は、こちらにまとめています。
実装結果
注文画面(/shopping)に、チェックボックスが設置されました。今回はお支払い方法の下に置いています。
実装後の注文画面(/shopping)
フォームはお支払い方法の下に設置
注文確認画面(/shopping/confirm)の表示は、チェックの有無で切り替わります。
チェックしなかった場合
「領収書:不要」と表示される
チェックした場合
「領収書:必要」と表示される
あわせて、dtb_order テーブルの receipt プロパティの値も、チェックの有無に応じて変化します。
うまくいかないときの確認ポイント
| 症状 | 確認するところ |
|---|---|
| 注文は通るが、チェックが保存されていない | OrderTypeExtensionの skip_add_form の分岐が抜けていないか。無条件に項目を足すと、注文処理へ進む場面で値が上書きされます |
receipt が見つからない、というエラーになる |
Proxyの生成・キャッシュの削除・データベースへの反映を、順に実行したか。Traitを置いただけでは認識されません |
| 確認画面に何も表示されない | 確認画面で form.receipt を書いていないか。確認画面は Order.receipt です |
まとめ
- 注文情報への項目追加は、
app/Customize/Entityに置くTraitで行う。コアのファイルは触らない - 反映にはProxyの生成・キャッシュの削除・データベースへの反映の3コマンドが必要
- フォームの追加はOrderTypeExtension。
skip_add_formが有効なときは項目を足さないのが必須条件 - 注文画面のフォームはShoppingControllerから渡されているので、Controllerのカスタマイズは不要
- 表示は、入力画面が
form.receipt、確認画面がOrder.receipt

あわせて読みたい
EC-CUBE 4 カスタマイズのまとめ
EC-CUBE 4について、筆者自身が学習・実践してきたカスタマイズ方法をまとめています。はじめて触る方向けに、手を動かす順番も並べました。
EC-CUBEのカスタマイズに関する記事
- カスタマイズのまとめ
- 既存テーブルに新しいフィールド(カラム)を追加する
- FormExtensionを使ったFormTypeのカスタマイズ
- ドロップダウンリスト / ラジオボタン / チェックボックスの実装方法
- 商品登録にオリジナルの新規項目を追加する
- デバッグモードの設定/解除方法
- 遭遇したエラー&対処法まとめ

