EC-CUBEのFormの仕組み

# EC-CUBEでPOSTする

## 基本編
### EC-CUBEでのPOSTの流れ

1. Controller：Entityを基にFormTypeを作成し、Twigに渡す
2. Twig：Formを表示し、Controllerへsubmitする
3. Controller：submitしたFormを受け取る

基本的な流れをまとめている記事があったので、具体的なソースは以下の記事を参照
https://qiita.com/yutachaos/items/0ae0d1797db4cb16466c

## 応用編
### 1. データの加工
Form Eventsを使用することで、任意のタイミングでデータを加工することができます。

以下の記事に概要がまとめられていました。
https://qiita.com/yutachaos/items/a5d2ee34fdf40c2b701f

公式ドキュメントにさらに詳しいイベント発火タイミングが記載されています。
https://symfony.com/doc/current/form/events.html


### 2. widgetの編集
EC-CUBEでは、Twig上では```{{ form_widget(form.foo) }}```と記述すると、勝手に```input[type=radio]```が```<div></div>```でグルーピングされていたり、form_errorの表示形式が指定されていたりします。

開発にあたり不都合がある場合は、以下の方法でデザインカスタマイズを行うことができます。
1. ```src/Eccube/Resource/template/default/Form/form_div_layout.twig```をコピーし、```app/template/default/Form/form_prod_layout.twig```に配置する
2. レイアウトを適用したいTwigに以下を記載する
```{% form_theme form '/Form/form_prod_layout.twig' %}```
3. form_layoutをカスタマイズする

###### 例）日付選択時にエラーがあった場合は選択肢それぞれにエラーデザインを適用する
````shopping.twig
{% extends 'default_frame.twig' %}
{% form_theme form '/Form/form_prod_layout.twig' %} 　　// 追記

{% block stylesheet %}
{% endblock stylesheet %}

{% block main %}

    // 省略

    {{ form_widget(form.birthday) }}

    // 省略
    
{% endblock %}

````
````form_div_layout.twig
{%- block date_widget -%}
    {%- if widget == 'single_text' -%}
        {{ block('form_widget_simple') }}
    {%- else -%}
        <div {{ block('widget_container_attributes') }}>
            {{- date_pattern|replace({
                '{{ year }}':  form_widget(form.year),
                '{{ month }}': form_widget(form.month),
                '{{ day }}':   form_widget(form.day),
            })|raw -}}
        </div>
    {%- endif -%}
{%- endblock date_widget -%}
````
````form_prod_layout.twig
{%- block date_widget -%}
    {%- if widget == 'single_text' -%}
        {{ block('form_widget_simple') }}
    {%- else -%}
        // 表示形式を指定
        {% set date_pattern = '{{ year }}年{{ month }}月{{ day }}日' %}
        // エラーの場合にエラーデザインを適用
        {%- if errors|length > 0 -%}
            <li {{ block('widget_container_attributes') }} class="date_select">
                {{- date_pattern|replace({
                    '{{ year }}':  form_widget(form.year, {'attr': {'class': ' error '}}),
                    '{{ month }}': form_widget(form.month, {'attr': {'class': ' error '}}),
                    '{{ day }}':   form_widget(form.day, {'attr': {'class': ' error '}}),
                })|raw -}}
            </li>
        {%- else -%}
            <li {{ block('widget_container_attributes') }} class="date_select">
                {{- date_pattern|replace({
                    '{{ year }}':  form_widget(form.year),
                    '{{ month }}': form_widget(form.month),
                    '{{ day }}':   form_widget(form.day),
                })|raw -}}
            </li>
        {%- endif -%}
    {%- endif -%}
{%- endblock date_widget -%}

````



Symfonyが提供している大元のファイルは以下
```vendor/symfony/twig-bridge/Resources/views/Form/form_div_layout.html.twig```

#### widgetを使用しない方法
radioの選択肢によって制限を設ける場合等に使えます。
以下参考
https://it-engine.tech/blogs/1043

###### 例）会員登録必須商品(Order.getCustomerRankByProduct > 0)の場合は法人選択不可とする

````shopping.twig
<dl class="contactDl">
    <dt><span class="txtSpan">必須</span>個人・法人</dt>
    <dd>
        <ul class="radioUl ">
            {% for key, item in form.corporate_flg.children %}
                <li><label><input type="radio" id="{{ item.vars.id }}" name="{{ item.vars.full_name }}" value="{{ item.vars.value }}" {{ item.vars.checked ? 'checked' : '' }}{% if Order.getCustomerRankByProduct > 0 and key == 1 %} disabled{% endif %}><span>{{ item.vars.label }}</span></label></li>
            {% endfor %}
        </ul>
        {{ form_errors(form.corporate_flg) }}
    </dd>
</dl>

````