🎻

[Symfony/Form] 子FormTypeの特定の項目をそのユースケースでのみ必須にする方法

2020/12/06に公開

Symfony Advent Calendar 2020 の6日目の記事です!🎄🌙小ネタですみません!

昨日も僕の記事で、[Symfony] コレクションプロパティのバリデーションにおいて子オブジェクト側のNotBlank制約が無視されるケースについて でした✨

ちなみに、僕はよく TwitterにもSymfonyネタを呟いている ので、よろしければぜひ フォローしてやってください🕊🤲

あと、この記事とよく似た内容の以下のような記事もあるので、よろしければあわせてご参照ください🤲
[Symfony/Form] 継承元のFromTypeの項目のオプションを部分的に変更する方法

やりたいこと

例えば、アプリ内に住所を入力する画面がいくつかあって、以下のように AddressType という住所入力用のFormTypeを部品化しているとします。

class AddressType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('zipCode', TextType::class, [
                'required' => false,
                'label' => '郵便番号',
            ])
            ->add('prefecture', TextType::class, [
                'required' => false,
                'label' => '都道府県',
            ])
            ->add('city', TextType::class, [
                'required' => false,
                'label' => '市区郡',
            ])
            ->add('line1', TextType::class, [
                'required' => false,
                'label' => '町名・番地',
            ])
            ->add('line2', TextType::class, [
                'required' => false,
                'label' => '建物名・号室',
            ])
        ;
    }
}

基本的にはどの項目も必須でないのですが、とある画面においてのみ、都道府県だけは必須にしたい という要件が出てきたとしましょう。

こういう場合の対処方法について説明します。

やり方

やり方はすごく簡単で、この AddressType を使っているFormType側で、

  1. $builder->get('address')->get('prefecture')->getOptions()prefecture フィールドのオプションを取得
  2. オプションの内容を部分的に変更
  3. $builder->add() し直す

だけです👍

class FooType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('hoge', TextType::class, [
                'label' => 'ほげ',
            ])
            ->add('fuga', TextType::class, [
                'label' => 'ふが',
            ])
            ->add('address', AddressType::class, [
                'label' => '住所',
            ])
        ;

        // 既存項目のオプションを部分的に変更してaddし直す
        $fieldOptions = $builder->get('address')->get('prefecture')->getOptions();
        $fieldOptions['required'] = true;
        $fieldOptions['constraints'] = [
            new Assert\NotBlank(),
        ];
        $builder->get('address')->add('prefecture', TextType::class, $fieldOptions);
    }
}

簡単ですね!

[Symfony/Form] 継承元のFromTypeの項目のオプションを部分的に変更する方法

こちらの過去記事で継承元の項目をいじったときとやっていることはまったく同じです👌

場合によっては、

$fieldOptions['required'] = true;

だけでなく

$fieldOptions['attr']['required'] = true;
$fieldOptions['label_attr']['class'] = 'required';
// または
// $fieldOptions['label_attr']['class'] .= ' required';

などが必要なこともあるかもしれません。その理由については↓昨日の記事をご参照ください✋

[Symfony] コレクションプロパティのバリデーションにおいて子オブジェクト側のNotBlank制約が無視されるケースについて

以上です!

Symfony Advent Calendar 2020、明日はまた僕です!笑 お楽しみに!

GitHubで編集を提案

Discussion