Symfony/FormコンポーネントのChoiceTypeのラジオボタンをバラバラに表示する方法

分かりづらいタイトルですが、Symfonyの[Formというコンポーネント](https://symfony.com/doc/current/components/form.html)に関する話です。

HTMLフォームの表示やバリデーションを行うコンポーネントなのですが、これを使うと簡単にラジオボタンの選択ができます。

例えば。

![支払い方法１](https://qiita-image-store.s3.amazonaws.com/0/31171/1a145dca-be5a-1604-4ed1-78e570be2265.png)

うん、悪くないです。でも…

クレジットカードと銀行振込、それぞれに必要な入力欄を一緒に表示するにはどうしたらいいでしょう？要するに、ラジオボタンを任意の場所に表示して、こんなフォームを作りたいのです。

![支払い方法２](https://qiita-image-store.s3.amazonaws.com/0/31171/0f146e54-2fef-1ccf-98b2-e554672f0e5f.png)

### インストールなど

確認したのはSymfonyのVersion 4.1。

まずは[Symfonyのインストール](https://symfony.com/doc/current/setup.html)。

```
composer create-project symfony/website-skeleton sym-radio-test
```

フォームオブジェクトの作成
-----

まずはControllerでフォームオブジェクトを作成してみます。

```php
class ChoiceController extends Controller
{
    /**
     * @Route("")
     */
	public function form(): Response
	{
        $form = $this->createFormBuilder()
            ->add('payment', ChoiceType::class, [
                'choices'  => [
                    'クレジットカード'   => 'credit',
                    '銀行振込' => 'bank',
                ],
                'expanded' => true,
                'label' => '支払い方法',
            ])
            ->add('credit', TextType::class, [
                'label' => 'カード番号',
            ])
            ->add('bank', TextType::class, [
                'label' => '振込人名義',
            ])
            ->getForm();
        return $this->render("form.html.twig", [
            'form' => $form->createView(),
        ]);
	}
}
```

`payment`がラジオボタンになります。`ChoiceType::class`を指定した上に`expanded`に`true`を指定します。


### 普通にフォームを表示

せっかくなので、bootstrapレイアウトを利用してみます。

```twig
{% extends("base.html.twig") %}

{% form_theme form 'bootstrap_4_horizontal_layout.html.twig' %}

{% block body %}
    <h1>支払い方法</h1>

    <p class="text-info">クレジットカードを選択したらカード番号を、銀行振込を選択したら振込人名義を記入してください。</p>
    {{ form_start(form) }}
    {{ form_widget(form) }}
    <input type="submit" class="btn btn-primary" value="enter" />
    {{ form_end(form) }}
    
{% endblock %}
```

これだけで、すごくきれいなフォームを表示してくれます。

![form1.png](https://qiita-image-store.s3.amazonaws.com/0/31171/1a145dca-be5a-1604-4ed1-78e570be2265.png)

慣れれば`Symfony/Form`は非常に簡単に綺麗なフォームを作れると思う。

ラジオボタンを任意の位置に表示してみる
-----

フォーム表示が簡単にできるのはいいけれど、どこまで自由度があるかも大事。最初のフォームの場合なら、クレジットカードや銀行振込に関するフォームは、それぞれまとめて表示してみます。

実はラジオボタンは配列になっていて、

```
{{ form_widget(form.payment[0] }}
```

とすることで`payment`の各ラジオボタンを表示できます。

これを利用して、先のHTMLフォームを工夫してみます…

```twig
{% extends("base.html.twig") %}

{% form_theme form 'bootstrap_4_horizontal_layout.html.twig' %}

{% block body %}
    <h1>支払い方法２</h1>
    
    <p class="text-primary">クレジットカードか銀行振込を選択してください。</p>

    {{ form_start(form) }}
    <div class="row form-group">
        <div class="col-sm-12">
            <span class="text-info">クレジットカードを選択したら、カード番号を記入してください。</span>
            {{ form_widget(form.payment[0]) }}
            {{ form_row(form.credit) }}
        </div>
    </div>
    <div class="row">
        <div class="col-sm-12">
            <span class="text-info">銀行振込を選択したら、振込人名義を記入してください。</span>
            {{ form_widget(form.payment[1]) }}
            {{ form_row(form.bank) }}
        </div>
    </div>
    <input type="submit" class="btn btn-primary" value="enter" />
    {{ form_end(form) }}
    
{% endblock %}    
```

すると…

![支払い方法２](https://qiita-image-store.s3.amazonaws.com/0/31171/0f146e54-2fef-1ccf-98b2-e554672f0e5f.png)

ちょっとHTMLは複雑ですが、狙い通りになりました。