ベルンハルトが指摘したように、データはまだサブフォームで利用できないため、リスナーはこれを行う唯一の方法です。同様の要件を解決するために eventListener を使用しました。以下は、役立つと思われる私のコードの簡略版です。
多くのフィールドを持つエンティティの親フォームと、View
他のフォームのコレクションがあります。サブフォームの 1 つは関連付けられたエンティティ用ViewVersion
であり、実際には に関連付けられたコンテンツ タイプである動的エンティティ用の別のフォーム コレクションをロードする必要がありますView
。このコンテンツ タイプは、Article、Profile など、さまざまな種類のエンティティの 1 つです。そのため、View
データに設定されている contentType を調べ、そのバンドルへの動的パスを見つけて、その formType を含める必要があります。
やり方がわかれば、実は簡単!
class ViewType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
// Basic Fields Here
// ...
// ->add('foo', 'text')
// ...
// Load a sub form type for an associated entity
->add('version', new ViewVersionType())
;
}
}
class ViewVersionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
// Basic Fields Here
// ...
// ->add('foo', 'text')
// ...
;
// In order to load the correct associated entity's formType,
// I need to get the form data. But it doesn't exist yet.
// So I need to use an Event Listener
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
// Get the current form
$form = $event->getForm();
// Get the data for this form (in this case it's the sub form's entity)
// not the main form's entity
$viewVersion = $event->getData();
// Since the variables I need are in the parent entity, I have to fetch that
$view = $viewVersion->getView();
// Add the associated sub formType for the Content Type specified by this view
// create a dynamic path to the formType
$contentPath = $view->namespace_bundle.'\\Form\\Type\\'.$view->getContentType()->getBundle().'Type';
// Add this as a sub form type
$form->add('content', new $contentPath, array(
'label' => false
));
});
}
}
それでおしまい。私は Symfony に慣れていないので、EventListener ですべてを行うという考えは私にはなじみがありません (そして、不必要に複雑に思えます)。しかし、フレームワークをよりよく理解すると、より直感的に見えるようになることを願っています. この例が示すように、イベント リスナーでそれを行うのはそれほど複雑ではありません。コードをそのクロージャでラップするだけです (または、ドキュメントで説明されているように独自の別の関数に配置します)。
それが誰かを助けることを願っています!