EC-CUBE3.0ではフォームの入出力やバリデーションにはFormTypeで実装されています。
FormTypeの使い方はSymfonyのドキュメントにもありますが、その中でもちょっと理解するのが難しい、フォームイベントについてまとめてみます。
フォームイベントって?
フォームにかぎらずなのですが、symfonyではイベントという概念で、処理の途中で別の処理を差し込める仕組みが有ります。
FormTypeで用意されているイベントは、以下のとおりです。
- PRE_SET_DATA
- POST_SET_DATA
- PRE_SUBMIT
- SUBMIT
- POST_SUBMIT
また、フォームイベントのフローも公式ドキュメントで提供されています。
http://symfony.com/doc/current/components/form/form_events.html
実際に動かしてみる
前述のSymfonyの公式ドキュメントを参照するのが一番手っ取り早いのですが、実際に動かしてみるのが一番理解しやすいかと思います。
EC-CUBE3.0のソースコードにフォームイベントを追加して、動かしてみましょう。
管理画面の特定商取引法の設定画面のソースコードを少しいじってみます。
src/Eccube/Controller/Admin/Shop/TradelawController.php
public function index(Application $app)
{
$Help = $app['eccube.repository.help']->get();
// ★ フォーム生成前
echo "CONTROLLER: CREATE FORM BEFORE".PHP_EOL;
$form = $app['form.factory']
->createBuilder('tradelaw', $Help)
->getForm();
// ★ フォーム生成後
echo "CREATE FORM AFTER".PHP_EOL;
if ('POST' === $app['request']->getMethod()) {
// ★ handleRequest実行前
echo "CONTROLLER: HANDLE REQUEST BEFORE".PHP_EOL;
$form->handleRequest($app['request']);
// ★ handleRequest実行後
echo "CONTROLLER: HANDLE REQUEST AFTER".PHP_EOL;
if ($form->isValid()) {
$Help = $form->getData();
$app['orm.em']->persist($Help);
$app['orm.em']->flush();
$app->addSuccess('admin.register.complete', 'admin');
return $app->redirect($app->url('admin_setting_shop_tradelaw'));
} else {
$app->addError('admin.register.failed', 'admin');
}
}
return $app->render('Setting/Shop/tradelaw.twig', array(
'form' => $form->createView(),
));
}
src/Eccube/Form/Type/Admin/TradelawType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('law_company', 'text', array(
'label' => '販売業者',
'required' => true,
'constraints' => array(
new Assert\NotBlank(),
),
))
...
->addEventSubscriber(new \Eccube\Event\FormEventSubscriber());
// ★イベントを設定
$builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
echo "FORM: PRE_SET_DATA".PHP_EOL;
});
$builder->addEventListener(FormEvents::POST_SET_DATA, function(FormEvent $event) {
echo "FORM: POST_SET_DATA".PHP_EOL;
});
$builder->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $event) {
echo "FORM: PRE_SUBMIT".PHP_EOL;
});
$builder->addEventListener(FormEvents::SUBMIT, function(FormEvent $event) {
echo "FORM: SUBMIT".PHP_EOL;
});
$builder->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
echo "FORM: POST_SUBMIT".PHP_EOL;
});
}
ソースコードを書き換えた状態で、特定商取引法の登録を実行すると、以下が出力されます。
CONTROLLER: CREATE FORM BEFORE
FORM : PRE_SET_DATA
FORM : POST_SET_DATA
CONTROLLER: CREATE FORM AFTER
CONTROLLER: HANDLE REQUEST BEFORE
FORM : PRE_SUBMIT
FORM : SUBMIT
FORM : POST_SUBMIT
CONTROLLER: HANDLE REQUEST AFTER
SET_DATA系のイベントはフォーム生成時、SUBMIT系のイベントは、handleRequestが実行されたタイミングで実行されます。
PREとかPOSTとかはどう違うの?という点では、FormTypeのコードをみてみるのがよいかもしれません。
PRE_SET_DATA
https://github.com/symfony/form/blob/2.7/Form.php#L342
POST_SET_DATA
https://github.com/symfony/form/blob/2.7/Form.php#L391
PRE_SUBMIT
https://github.com/symfony/form/blob/2.7/Form.php#L546
SUBMIT
https://github.com/symfony/form/blob/2.7/Form.php#L633
POST_SUBMIT
https://github.com/symfony/form/blob/2.7/Form.php#L660
なにができるの?
主に動的にフォームを生成する必要がある場合によく使います。
EC-CUBE3.0では、このへんで利用されています。
ぜひ参考にしてみてください。
12/3は、 @shinichi-takahashi さんです!