エンティティのフォーム作成をもっと簡略化するには?
この記事では、「新たにエンティティのタイプクラスを作ってフォームを自動生成する」方法について紹介しています。
デフォルトではOrderTypeやContactTypeなどのFormTypeと呼ばれるファイルが用意されており、それぞれ注文や問い合わせのフォームを呼び出すときに使われています。一方、自身でオリジナルテーブルを作成した場合はそれに紐づくFormTypeはないため、本記事で簡単なFormTypeを作成します。
なお、デバッグモードを設定しておくと、エラーが起きたときに詳細情報が表示されるようになります。
エラー箇所を探しやすくなるので、開発前に設定しておくのをオススメします。
デバッグモードの設定方法については こちらの記事 で解説しています。
FormTypeとは
一般に『エンティティ名 + Type.php』という名前で作成され、エンティティ自体をTextTypeやIntegerTypeのように1つのタイプとして定義したものです。タイプは以下のような形で構成されます。
class タイプ名 extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
// Formの生成コードを記述
}
public function configureOptions(OptionResolver $resolver)
{
// 必要な情報を設定
}
}
ここで定義したタイプクラスをControllerで呼び出す(createFormメソッドを使用する)ことで、Controllerではフォーム生成のコードを省き、フォーム生成部分のコードを切り分けることができます。
タイプクラスを新規に作成する
本記事では、オリジナルテーブルとして『dtb_Maker』を使い、新しいレコードが追加できるようControllerとTwigを準備した状態からの手順となります。詳しくは以下記事をご覧ください。
- 【EC-CUBE 4】オリジナルテーブルをデータベースに新規で追加する方法
(メーカー情報を保存できるテーブル・『dtb_Maker』を作成します。) - 【EC-CUBE 4】オリジナルテーブルに新規データ(レコード)を追加する方法
(上記で作成した『dtb_Maker』に、Webページからフォームを送信してレコードを追加できるようにします。ただFormTypeには触れていないため、本記事で作成します。)
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つのメソッドが定義されています。
引数で渡されたFormBuilderからaddを呼び出し、フォームの項目を生成します。こちらの記事で作成したControllerのフォーム生成部分をそっくり移行した形です。
setDefaultsというメソッドを呼び出し、’data_class’という値にデータとして設定されるクラスをセットします。
タイプクラスを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;
// MakerTypeを追加し、TestTypeと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)
{
$maker = new Maker();
// createFormBuilderの代わりにcreateFormを使用
// 引数にはMakerTypeクラスとMakerインスタンスを引数に指定
// add~getForm()までは削除
$form = $this->createForm(MakerType::class, $maker);
$form->handleRequest($request);
if ($request->getMethod() == 'POST') {
$maker = $form->getData();
$manager = $this->getDoctrine()->getManager();
$manager->persist($maker);
$manager->flush();
return [
'message' => '登録完了しました!',
'form' => $form->createView(),
];
} else {
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メソッドを使う一文のみでフォームが生成できるようになります。コードがスッキリして他にも使い回せるので、ぜひ積極的に使っていきたい機能ですね。