使用值填充Symfony2自定义字段类型 [英] Symfony2 Custom Field Type from Populate with values

查看:121
本文介绍了使用值填充Symfony2自定义字段类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是先前问题 Symfony2自定义表单类型或扩展名的后续内容

This is a follow on from the earlier question Symfony2 Custom Form Type or Extension

我正在尝试在订单上附加产品的自定义字段类型.名称字段将包含产品名称,而ID字段将包含产品ID.

I am trying to attach a custom field type for Product on an Order. The name field will contain the product name and the id field the product id.

我正在使用FormEvents :: PRE_SET_DATA尝试填充数据,但会引发错误,getData()返回Form \ Type \ ProductAutoCompleteType.

I am using FormEvents::PRE_SET_DATA to try and populate the data but it throws an error, getData() returns Form\Type\ProductAutoCompleteType.

我该如何更正代码?

OrderType具有以下内容:

OrderType has the following:

    $builder->add('product', new Type\ProductAutoCompleteType(), array(
        'data_class' => 'Acme\TestBundle\Entity\Product'
    ));        

ProductAutoCompleteType:

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()

Error: FatalErrorException: Error: Call to a member function getProduct() on a non-object in /var/www/symblog/src/Acme/TestBundle/Form/Type/ProductAutoCompleteType.php line 26

控制器

    $em = $this->getDoctrine()->getManager();
    $order = $em->getRepository('AcmeTestBundle:Order')->find(6);

    $form = $this->createForm(new OrderType(), $order);

已更新2

更改字段[product] [id]并提交表单后,现在出现以下错误,我认为这是因为字段名称是[product] [id]而不是[product]?

After changing the field [product][id] and submitting the form I now get the following error, I assume this is because the field name is [product][id] and not [product]?

属性"id"或方法"setId()"," set()"或"__call()"都不存在,并且在类"Proxies__CG \ Acme \"中具有公共访问权限TestBundle \ Entity \ Product".

Neither the property "id" nor one of the methods "setId()", "set()" or "__call()" exist and have public access in class "Proxies__CG\Acme\TestBundle\Entity\Product".

已更新3

我现在已经将数据提交给控制器,在提交控制器时,我不得不添加以下内容,以这种方式进行验证和附加产品看起来很麻烦,这是正确的方法吗?

I have it submitting data to the controller now, in my controller on submit I have had to add the following, it looks messy to do validation and attach the product this way, is this the right way?

        $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'));
            }
        }

推荐答案

将所有逻辑放入控制器中不是一个好习惯.您的表单应尽可能多地处理这些表单,以确保这些表单的可重用性.

Putting all your logic into the controller is not a good practice. Your forms should handle as much of this as possible to ensure reusability of these forms.

如果查询的订单中没有相关产品,则$form->getData()返回null是正常的.

If the Order that you query does not have a related product in it, then it's normal that $form->getData() returns null.

调试技巧:

输出$form->getData()的值以检查Product对象. 输出$form->getParent()->getData()的值以检查父窗体中的Order对象.

Output the value of $form->getData() to inspect the Product object. Output the value of $form->getParent()->getData() to inspect the Order object from the parent form.

验证提示:

如果这种形式的产品可以为空,请确保仅在产品不为空的情况下设置名称字段的数据.

In case a product in this form can be null, make sure that you only set the name field's data if the product is not null.

查询提示:

由于存储库中的findBy方法不会自动包含相关的product,因此我建议使用QueryBuilder并进行联接.控制器中的示例:

Since the findBy method on the repository will not automatically include the related product, I recommend using a QueryBuilder and make a join. Example in the controller:

$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();

当然,在控制器中包含太多代码也不是一件好事,因此,一旦工作正常,请使用自定义方法创建一个自定义存储库,并将此代码移到那里.

Of course, having so much code in your controller is not great either, so once you get your stuff working, create a custom repository with a custom method and move this code there.

在您的实体中:

/**
 * @Entity(repositoryClass="Acme\TestBundle\Repository\OrderRepository")
 */
class Order {

在您的存储库中

class OrderRepository {
  public function findByIdWithProduct() {
    // $order = $this->createQueryBuilder...
    return $order;
  }
}

这篇关于使用值填充Symfony2自定义字段类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆