How to handle Symfony form collection with 500+ items

人走茶凉 提交于 2019-12-23 09:31:56

问题


I have form collection which need to handle more than 500 entity instances. After I increased timeout to 60s and increased max_input_vars form work but it is annoying how slow it is. Rendering form is slow but submitting that big form is pain in the ass.

I was considering creating plain HTML form but there is some other drawback suck as validation. So, is there any proper way to handle that big set of data via symfony form ?

CONTROLLER:

public function ratesCardAction() {
    $bannerList = $this->data;

    $em = $this->getDoctrine()->getManager();
    $form = $this->createForm(new AdvertiserRatesType($bannerList));
    if ('POST' == $this->getRequest()->getMethod()) {
        $form->handleRequest($this->getRequest());
        $advertiserCampaign = $form->getData();
        if ($form->isValid()) {
            foreach ($advertiserCampaign['campaignsAdZones'] as $campaignAdZone) {
               $em->persist($campaignAdZone);
            }
            $em->flush();
        }
    }

    return array(
        'form'   => $form->createView()
    );
}



class AdvertiserRatesType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder ->add('campaignsAdZones', 'collection', array(
            'type'   => new AdvertiserRatePerCountryType(),
            'data'   => $this->rates,
            'empty_data'  => null,
            'options'  => array(
                'attr' => array('class' => 'campaignAdZoneItem')
            )
        ))
        ;
    }

}

...

and embedded form looks like:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('class', 'entity', array(
                'class' => 'AcmeCmsBundle:PublisherTypes',
                'property' => 'class',
                'read_only' => true,
                'disabled' => true
            )
        )
        ->add('country', 'entity', array(
                'class' => 'AcmeCmsBundle:Countries',
                'property' => 'name',
            )
        )
        ->add('text1')
        ->add('text2')
    ;
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'Acme\CmsBundle\Entity\Rates'
    ));
}

回答1:


Indeed using whole entities to collection with over 500 items is an overkill ;)

First: use pure arrays instead of entities, set 'data_class' => null in setDefaultOptions method

Second: You do not want to create over 500 new items on one page form, do You? ;) If it is really needed for some reason and it has to be done like that... well currently $advertiserCampaign = $form->getData(); in Your code will return over 500 objects - HEAVY. Instead of that, $advertiserCampaign = $form->getData(); should return 500 arrays of data and THEN inside foreach You should create new object and bind data to it (e.g. using datatransfomer). Validation still may be handled with no problem - just set validators for each field inside form class.

Third: I hope that $this->rates is not another collection of objects - right? In case it is - use primitive array instead of heavy objects.

Fourth: 500 objects/forms on one page? REALLY? Might it be refactored somehow? Maybe pagination and e.g. 20 forms per page? If You really, really need to save 500 objects from one form in one request, then I suggest, to use some Queue handler like RabbitMQ or Gearman to save all 500 objects in database.

I hope that helps somehow.




回答2:


May I suggest using the Doctrine query cache ? You're typically in a case where caches are a common solution.

  • https://coderwall.com/p/ry1y0a
  • http://docs.doctrine-project.org/en/latest/reference/caching.html

See about other Symfony caches as well, and don't hesitate to test as many PHP cache solutions as you find (see last link).



来源:https://stackoverflow.com/questions/18718952/how-to-handle-symfony-form-collection-with-500-items

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!