操作方法:优化Symfony的形式'性能?

时间:2014-11-06 11:11:57

标签: 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 = $form->createView();

    return $this->render(
        'AcmeMyBundle:Ajax:order_edit.html.twig',
        array(
            'form' => $formView,
        )
    );

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

我的 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') // 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,
        ));

购买类型

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

同样购买类型的监听器在这里并不重要。它在下面的Symfony分析器中表示为variant_retrievepurchase_form_creating。你可以看到大约需要200ms。

这里我把分析器的结果: SymfonyProfiler BlackFire Profiler BlackFire Profiler

正如您所看到的那样:$this->createForm(...)需要1011毫秒,$form->createView();需要2876毫秒,并且在树枝中渲染表格也非常慢:4335毫秒。正如blackfire profiler所述,所有交易都在ObjectHydrator::gatherRowData()UnitOfWork::createEntity()

方法createEntity()调用2223次,因为有一些字段与Variant实体映射并且表单类型为Entity。但是从上面的代码可以看出,变体没有entity种类型。我的VariantType是具有text的简单扩展modelTransformer表单类型。为了不弄乱所有内容,您可以在docs看到类似Type类的代码。

我在XDebug中发现buildView的{​​{1}} VariantType已在Purchase的{​​{1}} buildView表单类型中调用。但是之后从text buildView再次调用了VariantType,在这种情况下,它具有entity表单类型。怎么可能?我尝试在choicespreferred_choices中为每个表单类型定义空数组,但它没有改变任何内容。我需要做些什么来防止为我的表单加载EntityChoiceList

2 个答案:

答案 0 :(得分:2)

所描述的行为看起来像猜测者的工作。我觉得需要显示一些额外的代码(听众,VariantTypeWebsiteTypePartnerType)。

让我们假设某个类有variantVariantFormType的关联,这个类的代码->add('variant')没有明确的指定类型(正如我在那里看到的那样)是很多没有指定类型的地方)。然后DoctrineOrmTypeGuesser进入游戏。

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

此代码将entity类型(!)分配给此子级。调用EntityRepository::findAll()并且DB的所有变体都是水合的。

至于其他表单优化方式:

  • 尝试在所有可能的情况下指定类型以防止类型猜测;
  • 使用SELECT和JOIN来获取订单,因为发送了对DB的新子请求以设置每个表单映射关系的基础数据;
  • 保留提交中的集合元素的键,因为删除单个元素而不保留密钥会触发不必要的更新。

答案 1 :(得分:0)

我对实体类型也有同样的问题,我需要列出城市,有像mire然后4000,我做的基本上是将选择注入表单。在您的控制器中,您从数据库中询问Variants,在存储库调用中,将它们水合为数组,并且只选择id和名称或标题,然后将其作为选项值传递到表单中。有了这个,数据库部分将更快。