これが私の最終的な解決策です。これが最善の方法であるかどうかわからないため、この回答は、より経験豊富な他の Symfony ユーザーがより良い解決策を考え出すことを奨励するために正しいとマークされていません。
このソリューションで気に入らない点は、製品エンティティ全体をフォームに渡すことができなくなり、オプション配列に各属性を個別に追加する必要があることです。
とにかく、それが現在実装されている方法です:
動的データは、オプション配列を createForm() の 2 番目のパラメーターとして使用して渡されます。
// ExampleController.php
use Acme\ExampleBundle\Entity\Product;
public function addAction()
{
// choices contains the dynamic data I am fetching from the webservice in my actual code
$choices = array("key1" => "value1", "key2" => "value2");
// now create a new Entity
$product = new Product();
// and some attributes already have values for some reason
$product->setPrice(42);
$form = $this->createForm(new AddproductType(),
array(
"choices" => $choices,
"price" => $product->getPrice()
)
);
if ($request->isMethod('POST')) {
$form->bind($request);
if ($form->isValid()) {
// ... standard symfony stuff here
}
}
return array(
'form' => $form->createView()
);
}
そしてフォームクラスです。イベント リスナー部分と setDefaultOptions メソッドに注意してください。
// ProductType.php
namespace Acme\ExampleBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$formFactory = $builder->getFormFactory();
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (\Symfony\Component\Form\FormEvent $event) use ($formFactory) {
// get the option array passed from the controller
$options = $event->getData();
$choices = $options["choices"];
$event->getForm()->add(
// add a new element with radio buttons to the form
$formFactory->createNamed("my_dynamic_field_name", "choice", null, array(
"empty_value" => "Choose an option",
"label" => "My dynamic field: ",
"choices" => $choices
)
)
);
}
);
// ... add other form elements
$builder->add("price", "text");
// ..
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
// register choices as a potential option
$resolver->setDefaults(array(
'choices' => null
));
}
}