【EC-CUBE 4】FormTypeを使ってフォームを生成する方法

エンティティのフォーム作成をもっと簡略化するには?

この記事では、「新たにエンティティのタイプクラスを作ってフォームを自動生成する」方法について紹介しています。

デフォルトではOrderTypeやContactTypeなどのFormType(フォームタイプ)と呼ばれるファイルが用意されており、それぞれ注文や問い合わせのフォームを呼び出すときに使われています。一方、自身でオリジナルテーブルを作成した場合はそれに紐づくFormTypeはないため、本記事で簡単なFormTypeを作成します。

開発前にデバッグモードの設定をお薦めします

デバッグモードを設定しておくと、エラーが起きたときに詳細情報が表示されるようになります。
エラー箇所を探しやすくなるので、開発前に設定しておくのをオススメします。
デバッグモードの設定方法については 以下記事 で解説しています。

カスタマイズ後は、デバッグモードの解除を忘れないように。

【動作環境】
EC CUBEのバージョン:4.3.0
サーバー:XServer

目次

FormType(フォームタイプ)とは

一般に、Symfonyのフォームタイプは 「エンティティ名 + Type.php」 という名前で作成されることが多く、エンティティの各プロパティを TextTypeIntegerType などのフォームフィールドとしてマッピングしたものです。

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;

class タイプ名 extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', TextType::class)
            ->add('age', IntegerType::class);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => エンティティ::class, // エンティティを関連付ける場合
        ]);
    }
}

ここで定義したフォームタイプクラスは、Controller で以下のように createForm() メソッドを使って呼び出します。

$form = $this->createForm(タイプ名::class, $entity);

タイプクラスを新規に作成する

本記事では、「dtb_maker」というテーブルを新規に作成し、「dtb_maker」に新しいデータ(レコード)を追加するためのWebページを準備した状態からの手順となります。詳しくは以下記事をご覧ください。

MakerTypeの作成

「MakerType.php」という名前で以下ファイルを作成し、「app/Customize/Form/Type」に格納します。(フォルダがなければフォルダも作成します。)

<?php

namespace Customize\Form\Type;

use Customize\Entity\Maker;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\OptionsResolver\OptionsResolver;

class MakerType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', TextType::class, array('label' => 'メーカー名'))
            ->add('code', TextType::class, array('label' => 'メーカーコード'))
            ->add('save', SubmitType::class, array('label' => 'Register'));
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Maker::class,
        ));
    }
}

このタイプクラスでは、以下2つのメソッドが定義されています。

buildForm()メソッド

このメソッドでは、FormBuilderInterfaceadd() メソッドを呼び出し、フォームに name(メーカー名)、code(メーカーコード)、save(登録ボタン)の3つのフィールドを追加しています。(以下記事で作成したControllerのフォーム生成部分をそっくり移行した形です。)

configureOptions()メソッド

このメソッドでは、setDefaults() メソッドを呼び出し、フォームのオプションを設定 します。ここでは、 'data_class'Maker::class を設定することで、フォームのデータとして Maker エンティティが使用されるようにしています。

タイプクラスをControllerで利用する

次はControllerでタイプクラスを呼び出すように修正し、フォーム生成はタイプクラス側で行います。

MakerRegisterControllerの修正

こちらの記事で用意したControllerを以下の通り修正します。

<?php

namespace Customize\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Eccube\Controller\AbstractController;
use Customize\Entity\Maker;
use Doctrine\ORM\EntityManagerInterface;

// MakerTypeを追加し、TextTypeとSubmitTypeは削除
use Customize\Form\Type\MakerType;

class MakerRegisterController extends AbstractController
{
  /**
   * @Route("/maker_register", name="maker_register")
   * @Template("maker_register.twig")
   */
  public function create(Request $request, EntityManagerInterface $entityManager)
  {
    $maker = new Maker();

    // createFormBuilderの代わりにcreateFormを使用
    // 引数にはMakerTypeクラスとMakerインスタンスを引数に指定
    // add~getForm()までは削除
    $form = $this->createForm(MakerType::class, $maker);

    if ($request->isMethod('POST')) {
      $form->handleRequest($request);

      if ($form->isSubmitted() && $form->isValid()) {
        $entityManager->persist($maker);
        $entityManager->flush();
        return [
          'message' => '登録完了しました!',
          'form' => $form->createView(),
        ];
      } else {
        return [
          'message' => '入力に誤りがあります。',
          'form' => $form->createView(),
        ];
      }
    }

    return [
    'message' => 'メーカー情報を新規登録します。',
    'form' => $form->createView(),
    ];
  }
}

コード中にも記載しましたが、修正箇所は以下の2箇所です。

use箇所
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

を削除し、

use Customize\Form\Type\MakerType;

を追加します。(フォーム生成はMakerTypeで行うため。)

フォーム生成箇所
$form = $this->createFormBuilder($maker)
      ->add('name', TextType::class, array('label' => 'メーカー名'))
      ->add('code', TextType::class, array('label' => 'メーカーコード'))
      ->add('save', SubmitType::class, array('label' => 'Register'))
      ->getForm();

を、

$form = $this->createForm(MakerType::class, $maker);

に書き換えます。

以上で準備完了です。
念の為キャッシュを削除してからページにアクセスし、問題なく機能するか確認しましょう。

まとめ

本記事では、新しくFormTypeを作成してみました。

タイプクラスを定義すると、createFormメソッドを使う一文のみでフォームが生成できるようになります。コードがスッキリして他にも使い回せるので、ぜひ積極的に使っていきたい機能ですね。


よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次