Php 如何:优化Symfony表单的性能?

Php 如何:优化Symfony表单的性能?,php,symfony,doctrine-orm,symfony-forms,Php,Symfony,Doctrine Orm,Symfony Forms,我有一个表单,它是ajax请求的瓶颈 $order = $this->getDoctrine() ->getRepository('AcmeMyBundle:Order') ->find($id); $order = $order ? $order : new Order(); $form = $this->createForm(new OrderType(), $order); $formView =

我有一个表单,它是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',
        array(
            'form' => $formView,
        )
    );
为了更简洁的代码,我删除了秒表语句

我的订单类型有以下字段:

    $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类型还有一个侦听器,在这里并不重要。它在下面的Symfony profiler中表示为variant\u retrieve、purchase\u form\u creating。你可以看到它大约需要200毫秒

这里我把分析器的结果放在这里:

如您所见:$this->createForm。。。取1011ms,$form->createView;需要2876ms,而twig中的表单渲染也非常慢:4335ms。正如blackfire事件探查器所述,ObjectHyderator::gatherRowData和UnitOfWork::createEntity中的所有事务都是由事务处理程序完成的

方法createEntity调用了2223次,因为有一些字段映射为Variant entity并具有表单类型entity。但从上面的代码中可以看到,variant没有实体类型。我的VariantType是具有modelTransformer的简单扩展文本表单类型。为了不把你们能看到的所有类似类型的代码都搞乱,在


我发现XDebug在Purchase的buildView中使用文本表单类型调用了VariantType的buildView。但在此之后,再次调用了VariantType的buildView,在本例中,它具有实体表单类型。怎么可能呢?我试图在选项中定义空数组,并在我的每种表单类型上定义首选_选项,但它没有改变任何东西。我需要做什么来防止EntityChoiceList为我的表单加载?

我的实体类型也有同样的问题,我需要列出城市,比如mire then 4000,我所做的基本上是将选择注入表单中。在控制器中,您从数据库中请求变量,在存储库调用中,将其作为数组,然后仅选择id和名称或标题,然后将其作为选项值传递到表单中。有了这个,数据库部分将更快。

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

让我们假设某个类具有variant到variant的关联,而该类的FormType具有code->add'variant',但没有显式指定类型,因为我看到很多地方没有指定类型。然后,DoctrineOrmTypeGuesser加入了游戏

此代码指定实体类型!给这个孩子。调用EntityRepository::findAll,DB的所有变体都被水合

至于另一种形式的优化方式:

尝试在所有可能的情况下指定类型,以防止类型猜测; 使用SELECT with JOIN获取订单,因为向DB发送新的子请求以设置每个表单映射关系的基础数据; 在提交时保留集合元素的键,因为在不保留键的情况下删除单个元素将触发不必要的更新。
据我所知,至少在使用模板时,这可能是因为在dev环境中没有细枝缓存。最好在没有细枝的情况下分析脚本,并计算在这种情况下调用createEntity的次数。我会检查一下。如果没有细枝,它也会调用getEntity,所以createEntity正好2223次。您有多少产品和变体?您可以尝试在表单中没有产品集合的情况下测试它吗。如果它的速度比你知道的要快得多,那么这个集合就是负责的。您可以发布您的采购和订单实体吗?采购实体是否与其他实体有关联和关联?我想有很多人潜伏在某处。我不需要去拿任何东西。我有一个订单,订单有一次采购,那个采购有一个产品,那个产品有一个变体。我不需要任何实体的选择列表,它不是关于查询的。9对数据库的查询。我刚刚更新了我的问题以使其更清楚。正如你们从我的代码中可以看到的,我已经为variant form指定了类型。它具有带有转换侦听器的文本类型。网站和合作伙伴实体没有开销。生成的html是什么样子的?实体代码单选按钮、复选框或选择框出现在什么地方?我覆盖默认主题以生成隐藏输入,而不是变体选择类型的标准文本输入。对于Webiste和Partners,我生成了自己的带有覆盖表单主题的选择列表。我认为启用带有大多数通用代码{{formformform}的默认主题来查看vriant的实体将出现在哪个位置会很有用。这是不必要的。我可以从symfony调试工具栏中看到variantType中的代码字段具有实体类型。
    $builder
        ->add('amount')
        ->add('price')
        ->add('code', 'variant', array(
            'property_path' => 'variantEntity',
            'data_class' => '\Acme\MyBundle\Entity\Simpla\Variant'
        ))
    ;