我有一个描述包的symfony 2表单:
class PackageType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->setMethod('POST')
->add('deliveryNote')
->add('receiver', new ReceiverType());
// field stockitem exists, added dynamically NOT good
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'IREnterprise\AppBundle\Entity\Package',
'csrf_protection' => false,
'allow_extra_fields' => true
));
}
/**
* @return string
*/
public function getName()
{
return 'IREnterprise_AppBundle_package';
}
}
每个包都有1个接收器,以及与包关联的动态数量的包行,每个包行包含一个stockitem。
这个想法是用户能够添加现有的StockItems作为包装线。
我已经实现了,它看起来像这样: 每次用户单击addPackageLine时,都会将一个包行添加到表单中,并且他可以选择一个stockItem和该stockItem的数量。
无论如何,我不得不做一些破坏性的事情来绕过formBuilder。
所以控制器最终看起来像这样:
public function newPackageAction(Request $request)
{
$package = new Package();
$form = $this->createForm(new PackageType(), $package);
$form->handleRequest($request);
// Test if stock item belongs to user, and add to package
$formStockItems = $request->request->get('IREnterprise_AppBundle_package[stockItems]', null, true);
// This is bad ... very bad, should be a doctrine validation
if (empty($formStockItems)) {
$form->add('packageLines')->addError(new FormError('Package Lines cannot be null'));
}
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$package->setUser($this->getUser());
foreach ($formStockItems as $formStockItem) {
$stockItem = $em->getRepository('IREnterpriseAppBundle:StockItem')
->findByUserAndId($this->getUser(), $formStockItem['item']);
if (!empty($stockItem)) {
// Create a package line for the stock item, and add it the line to the package
$packageLine = new PackageLine();
$packageLine->setStockItem($stockItem);
$packageLine->setAmount($formStockItem['quantity']);
$packageLine->setPackage($package);
$package->addPackageLine($packageLine);
}
}
$em->persist($package);
$em->flush();
$response = View::create($package);
return $response;
}
return View::create($form, Response::HTTP_BAD_REQUEST);
}
我想以一种不那么强硬的方式做到这一点,所以form-> isValid()也验证了所有发送的packageLiens,因为我的表单错误搞砸了这种方法,有什么建议吗?
答案 0 :(得分:1)
在交响乐中使用“集合”表单类型。有关完整的详细信息,请参阅How to Embed a Collection of Forms文档,但基本原则是集合类型采用选项“type”,它指定集合中每个元素的表单类型。
您还可以指定“allow_add”和“allow_delete”选项以允许其动态调整大小。
使用“allow_add”还可以创建一种“原型”表单字段,javascript可以使用该字段为此集合中的新项目呈现表单