エンティティのフォーム作成をもっと簡略化するには?
この記事では、「新たにエンティティのタイプクラスを作ってフォームを自動生成する」方法について紹介しています。
デフォルトではOrderTypeやContactTypeなどのFormType(フォームタイプ)と呼ばれるファイルが用意されており、それぞれ注文や問い合わせのフォームを呼び出すときに使われています。一方、自身でオリジナルテーブルを作成した場合はそれに紐づくFormTypeはないため、本記事で簡単なFormTypeを作成します。
デバッグモードを設定しておくと、エラーが起きたときに詳細情報が表示されるようになります。
エラー箇所を探しやすくなるので、開発前に設定しておくのをオススメします。
デバッグモードの設定方法については 以下記事 で解説しています。
カスタマイズ後は、デバッグモードの解除を忘れないように。
FormType(フォームタイプ)とは
一般に、Symfonyのフォームタイプは 「エンティティ名 + Type.php」 という名前で作成されることが多く、エンティティの各プロパティを TextType
や IntegerType
などのフォームフィールドとしてマッピングしたものです。
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()メソッド
-
このメソッドでは、
FormBuilderInterface
のadd()
メソッドを呼び出し、フォームに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
メソッドを使う一文のみでフォームが生成できるようになります。コードがスッキリして他にも使い回せるので、ぜひ積極的に使っていきたい機能ですね。
