У меня есть сборка формы, которая должна обрабатывать более 500 экземпляров объектов. После того, как я увеличил тайм-аут до 60 секунд и увеличил работу max_input_vars, но это раздражает то, насколько медленным оно является. Форма рендеринга медленная, но представление этой большой формы – боль в заднице.
Я рассматривал возможность создания простой HTML-формы, но есть еще один недостаток, который можно отнести к проверке. Итак, есть ли подходящий способ обработки этого большого набора данных через форму symfony?
ДИСПЕТЧЕР:
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') ) )) ; } }
…
и встроенная форма выглядит так:
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' )); }
Действительно, использование целых объектов для коллекции с более чем 500 наименованиями является излишним;)
Во-первых: используйте чистые массивы вместо сущностей, установите 'data_class' => null
в методе setDefaultOptions
Второе: вы не хотите создавать более 500 новых элементов в одной форме страницы, не так ли? 😉 Если это действительно необходимо по какой-то причине, и это должно быть сделано так … хорошо в настоящее время $advertiserCampaign = $form->getData();
в вашем коде будет возвращено более 500 объектов – HEAVY. Вместо этого $advertiserCampaign = $form->getData();
должен возвращать 500 массивов данных и THEN внутри foreach. Вы должны создать новый объект и привязать к нему данные (например, используя datatransfomer). Проверка еще может быть решена без проблем – просто установите валидаторы для каждого поля внутри класса формы.
В-третьих: я надеюсь, что $this->rates
не является другой коллекцией объектов – не так ли? В случае, если это – использовать примитивный массив вместо тяжелых объектов.
Четвертое: 500 объектов / форм на одной странице? ДЕЙСТВИТЕЛЬНО? Может быть, он будет каким-то образом реорганизован? Может быть, разбиение на страницы и, например, 20 форм на страницу? Если вам действительно нужно действительно сохранить 500 объектов из одной формы в одном запросе, я предлагаю использовать некоторый обработчик очереди, такой как RabbitMQ или Gearman, чтобы сохранить все 500 объектов в базе данных.
Надеюсь, что это поможет.
Могу ли я предложить использовать кэш запросов Doctrine? Обычно вы находитесь в случае, когда кеши являются общим решением.
Смотрите также и другие тайники Symfony, и не стесняйтесь тестировать как можно больше PHP-кеш-решений (см. Последнюю ссылку).