如何:优化Symfony的表单?

编程入门 行业动态 更新时间:2024-10-27 23:18:31
本文介绍了如何:优化Symfony的表单?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我有一个表单是我的ajax请求的瓶颈。

$ order = $ this-> getDoctrine () - > getRepository('AcmeMyBundle:Order') - > find($ id); $ order = $ order? $ order:new Order(); $ form = $ this-> createForm(new OrderType(),$ order); $ formView = $ form-> createView(); return $ this-> render('AcmeMyBundle:Ajax:order_edit.html.twig',数组('form'=> $ formView ,));

为了更清晰的代码,我删除了秒表语句。

我的 OrderType 有下列字段:

$ builder - > add('status')// enum(string) - > add('paid_status')// enum(string) - > add('purchases_price')// int - > add('discount_price')// int - > add('delivery_price')// int - > add 'delivery_real_price',null,array('required'=> false))// int - > add('buyer_name')// string - > add('buyer_phone')/ / string - > add('buyer_email')// string - > add('buyer_address')// string - > add('comment')// string - > add('manager_comment')// string - > add('delivery_type')// enum(string) - > add('delivery_track_id')//字符串 - > add('payment_method')// enum(string) - > add('payment_id')// string - > add('reward')// int - > add('reward_status')// enum(string) - > add('container')// string - > add('partner')//实体:用户 - > add('website','website')//实体:网站 - > add('products','collection',array(// Entity:Purchase 'type'=> 'purchase','allow_add'=> true,'allow_delete'=> true,'by_reference'=> false,'property_path'=> 'purchase','error_bubbling'=>假,));

购买类型:

$ builder - > add('amount') - > add('price') - > add 'code','variant',array('property_path'=>'variantEntity','data_class'=>'\Acme\MyBundle\Entity\Simpla\Variant '));

另外购买类型有一个在此不重要的监听器。它在Symfony剖析器下面被表示为 variant_retrieve , purchase_form_creating 。你可以看到它需要大约200ms。

这里我将剖析器的结果:

如您所见: $ this-> createForm(...)需要1011ms, $ form-> createView(); 需要2876ms和form在树枝上渲染也很慢:4335ms。如blackfire profiler所述,所有的交易在 ObjectHydrator :: gatherRowData()和 UnitOfWork :: createEntity()中。 / code> createEntity()调用2223次,因为有一些字段与 Variant 实体,并具有表单类型实体。但是从上面的代码可以看出,对于变体,没有实体类型。我的 VariantType 是简单的扩展文本表单类型具有 modelTransformer 。不要搞砸所有的东西,你可以在 docs 。

我使用XDebug找到 buildView 对于 VariantType 已在中调用的 buildView 文本表单类型。但是之后,再次调用了 buildView for VariantType ,在这种情况下,它有实体表单类型。怎么可能?我试图在每个我的表单类型的选项和 preferred_choices 中定义空数组,但没有更改任何内容。我需要做些什么来防止为我的表单加载 EntityChoiceList

解决方案

所描述的行为看起来像是猜测者的工作。我有一种感觉,需要显示一些额外的代码(监听器, VariantType , WebsiteType , PartnerType )。

让我们假设一个类有一个关联 variant to这个类的变式和 FormType 有代码 - > add('variant')没有明确的指定类型(因为我看到有很多地方没有指定类型)。然后 DoctrineOrmTypeGuesser 进入游戏。

github/symfony/symfony/blob/2.7/src/Symfony/Bridge/ Doctrine / Form / DoctrineOrmTypeGuesser.php#L46

此代码分配实体类型(!)给这个孩子调用 EntityRepository :: findAll(),并且DB中的所有变体都是水合的。

关于另一个表单优化方法:

  • 尝试在所有可能的情况下指定类型以防止类型猜测;
  • 使用选择具有JOIN以获得订单,作为对DB的新的子请求被发送以设置每个表单映射关系的基础数据;
  • 将提交上的集合元素的密钥保留为删除没有密钥保护的单个元素将触发不必要的更新。

I have a form that is the bottleneck of my ajax-request.

$order = $this->getDoctrine() ->getRepository('AcmeMyBundle:Order') ->find($id); $order = $order ? $order : new Order(); $form = $this->createForm(new OrderType(), $order); $formView = $form->createView(); return $this->render( 'AcmeMyBundle:Ajax:order_edit.html.twig', array( 'form' => $formView, ) );

For more cleaner code I deleted stopwatch statements.

My OrderType has next fields:

$builder ->add('status') // enum (string) ->add('paid_status') // enum (string) ->add('purchases_price') // int ->add('discount_price') // int ->add('delivery_price') // int ->add('delivery_real_price', null, array('required' => false)) // int ->add('buyer_name') // string ->add('buyer_phone') // string ->add('buyer_email') // string ->add('buyer_address') // string ->add('comment') // string ->add('manager_comment') // string ->add('delivery_type') // enum (string) ->add('delivery_track_id') // string ->add('payment_method') // enum (string) ->add('payment_id') // string ->add('reward') // int ->add('reward_status') // enum (string) ->add('container') // string ->add('partner') // Entity: User ->add('website', 'website') // Entity: Website ->add('products', 'collection', array( // Entity: Purchase 'type' => 'purchase', 'allow_add' => true, 'allow_delete' => true, 'by_reference' => false, 'property_path' => 'purchases', 'error_bubbling' => false, ));

Purchase type:

$builder ->add('amount') ->add('price') ->add('code', 'variant', array( 'property_path' => 'variantEntity', 'data_class' => '\Acme\MyBundle\Entity\Simpla\Variant' )) ;

Also Purchase type has a listener that is not significant here. It is represented in Symfony profiler below as variant_retrieve, purchase_form_creating. You can see that it takes about 200ms.

Here I put the result of profilers:

As you can see: $this->createForm(...) takes 1011ms, $form->createView(); takes 2876ms and form rendering in twig is also very slow: 4335ms. As stated by blackfire profiler all the deal in ObjectHydrator::gatherRowData() and UnitOfWork::createEntity().

Method createEntity() called 2223 times because there is some field that mapped with Variant entity and has form type Entity. But as you can see from above code there is no entity types for variant. My VariantType is simple extended text form type that has modelTransformer. To not mess up everything you can see code for similar Type class at docs.

I found with XDebug that buildView for VariantType has been called in Purchase's buildView with text form type. But after that from somewhere buildView for VariantType was called again and in this case it has entity form type. How can it be possible? I tried to define empty array in choices and preferred_choices on every my form type but it didn't change anything. What I need to do to prevent EntityChoiceList to be loaded for my form?

解决方案

The described behavior looks as the work of the guesser. I have the feeling that there is need to show an some additional code (listeners, VariantType, WebsiteType, PartnerType).

Let's assume a some class has association variant to Variant and FormType for this class has code ->add('variant') without explicit specifying type (as I see there is a lot of places where the type is not specified). Then DoctrineOrmTypeGuesser comes in the game.

github/symfony/symfony/blob/2.7/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php#L46

This code assign the entity type (!) to this child. The EntityRepository::findAll() is called and all variants from DB are hydrated.

As for another form optimization ways:

  • Try to specify type in all possible cases to prevent a type guessing;
  • Use SELECT with JOINs to get an order as new sub-requests to DB are sent to set an underlying data for an every form maps relation;
  • Preserve keys for collection elements on a submission as a removing of a single element without a keys preserving will trigger unnecessary updates.

更多推荐

如何:优化Symfony的表单?

本文发布于:2023-10-10 22:55:29,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1479993.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:表单   Symfony

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!