这是我最终得到的解决方案。不确定这是否是最好的方法,所以这个答案没有被标记为正确,以鼓励其他更有经验的 Symfony 用户提出更好的解决方案。
我不喜欢这个解决方案的地方是,我不能再将整个产品实体传递给表单,而是必须将每个属性单独添加到选项数组中:
无论如何,这就是它现在的实现方式:
动态数据使用 options 数组作为 createForm() 的第二个参数传递:
// 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
));
}
}