这是早期问题Symfony2 Custom Form Type or Extension
的后续内容我正在尝试为订单附加Product的自定义字段类型。 name字段将包含产品名称,id字段包含产品ID。
我正在使用FormEvents :: PRE_SET_DATA来尝试填充数据,但是它会抛出错误,getData()返回Form \ Type \ ProductAutoCompleteType。
如何更正代码?
OrderType具有以下内容:
$builder->add('product', new Type\ProductAutoCompleteType(), array(
'data_class' => 'Acme\TestBundle\Entity\Product'
));
ProductAutoCompleteType:
class ProductAutoCompleteType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('name');
$builder
->add('id');
/* Turns out this is not needed any more
$builder->addEventListener(
FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
$product = $form->getData();
$form
->add('name', 'text', array('mapped' => false, 'data' => $product->getName()));
}
);
*//
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
}
public function getParent()
{
return 'form';
}
public function getName()
{
return 'productAutoComplete';
}
}
更新
错误:FatalErrorException:错误:在/var/www/symblog/src/Acme/TestBundle/Form/Type/ProductAutoCompleteType.php第26行中的非对象上调用成员函数getProduct()
控制器
$em = $this->getDoctrine()->getManager();
$order = $em->getRepository('AcmeTestBundle:Order')->find(6);
$form = $this->createForm(new OrderType(), $order);
更新2
更改字段[product] [id]并提交表单后,我现在收到以下错误,我认为这是因为字段名称是[product] [id]而不是[product]?
属性“id”和方法“setId()”,“ set()”或“__call()”之一都不存在,并且在“Proxies__CG \ Acme \”类中具有公共访问权限TestBundle \实体\产品”。
更新3
我现在已经将数据提交给控制器,在我的控制器上提交我不得不添加以下内容,看起来很麻烦做验证并以这种方式附加产品,这是正确的方法吗?
$data = $request->request->get($form->getName());
if ($data['product']['id']) {
$product = $em->getRepository('AcmeTestBundle:Product')->find($data['product']['id']);
if ($product) {
if ($product->getShop()->getId() != $order->getShop()->getId()) {
$form->get('product')->get('name')->addError(new FormError('Invalid shop product'));
}
$form->getData()->setProduct($product);
} else {
$form->get('product')->get('name')->addError(new FormError('A product must be selected'));
}
}
答案 0 :(得分:0)
将所有逻辑放入控制器并不是一个好习惯。您的表单应尽可能多地处理这些表单以确保这些表单的可重用性。
如果您查询的订单中没有相关产品,那么$form->getData()
返回null是正常的。
调试提示:
输出$form->getData()
的值以检查Product对象。
输出$form->getParent()->getData()
的值以从父表单检查Order对象。
验证提示:
如果此表单中的产品可以为null,请确保仅在产品不为空时才设置名称字段的数据。
查询提示:
由于存储库上的findBy
方法不会自动包含相关的product
,因此我建议使用QueryBuilder并进行连接。控制器中的示例:
$order = $em->getRepository('AcmeTestBundle:Order')
->createQueryBuilder('order')
->select('order, product')
->innerJoin('order.product', 'product')
->where('order.id = :order_id')
->setParameter('order_id', $order_id)
->getQuery()
->getOneOrNullResult();
当然,在你的控制器中拥有如此多的代码也不是很好,所以一旦你的东西工作,用自定义方法创建一个自定义存储库并将代码移到那里。
在您的实体中:
/**
* @Entity(repositoryClass="Acme\TestBundle\Repository\OrderRepository")
*/
class Order {
在您的资料库中
class OrderRepository {
public function findByIdWithProduct() {
// $order = $this->createQueryBuilder...
return $order;
}
}