减少表单Symfony2中的请求数量


Reduce the number of request in form Symfony2

我有一个表单类型和另一个表单类型包括第一个在他的一个字段。第二种表单类型用于显示实体列表

第一个表单类型:

<?php
namespace Test'GameBundle'Form;
use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolverInterface;
use Doctrine'ORM'EntityRepository;
class CityType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('nameEn')
            ->add('latitude')
            ->add('longitude')
            ->add('country','entity',array(
                'class' => 'GeoQuizzGameBundle:Country',
                'property' => 'nameEn',
                'query_builder' => function(EntityRepository $er) {
                    return $er->createQueryBuilder('c')
                              ->orderBy('c.nameEn', 'ASC');
                    },
            ))
        ;
    }
    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Test'GameBundle'Entity'City'
        ));
    }
    /**
     * @return string
     */
    public function getName()
    {
        return 'test_gamebundle_city';
    }
}

第二个实体:

namespace Test'AdminBundle'Form;
use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolverInterface;
use Test'GameBundle'Form'CityType;
class CityListType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('cities','collection', array(
                'type'=>new CityType(),
                'allow_add' => true,
                'by_reference' => false
            ))
        ;
    }
    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Test'AdminBundle'Entity'CityList'
        ));
    }
    /**
     * @return string
     */
    public function getName()
    {
        return 'test_adminbundle_citylist';
    }
}

和在控制器中创建表单:

public function listAction(Request $request)
{
    $cityRepository = $this->getDoctrine()->getRepository("GeoQuizzGameBundle:City");
    //get continents
    $cities = $cityRepository->findBy(
                array(),
                array('nameEn' => 'ASC')
            );
    $cityList = new CityList();
    foreach($cities as $city){
        $cityList->addCity($city);
    }
    $form = $this->createForm(new CityListType(),$cityList);
    $form->handleRequest($request);
    if($form->isValid()){
        $em = $this->getDoctrine()->getManager();
        foreach ($cityList->getCities() as $city){
            if(!$this->isCity($cities, $city)){
                $em->persist($city);
            }
        }
        $em->flush();
        return $this->redirect($this->generateUrl('geo_quizz_admin_city_list'));
    }
    return $this->render('GeoQuizzAdminBundle:City:list.html.twig',array(
        'form' => $form->createView()
    ));
}

我有196个请求124个字段,因为国家列表是查询每一行,有一个解决方案来防止它吗?

我可以在控制器中进行查询,并通过我的国家数组作为表单类型的参数,它是干净的吗?

您可以使用choice字段类型代替entity。所有你需要做的是有choices参数包含你的国家列表。

$countryChoices是一个国家的关联数组,您可以获取一次并在buildForm方法中使用它。我要这样做的方式是使您的表单服务,并传递ObjectManager构造器:

services.yml:

services:
    your_form:
        class: Test'GameBundle'Form'CityListType
        arguments: [@doctrine.orm.entity_manager]
        tags:
            - { name: form.type, alias: yourFormAlias }

你的CityType类:

class CityType extends AbstractType
{
     /**
     * @param ObjectManager $objectManager
     */
    public function __construct(ObjectManager $objectManager)
    {
        $this->objectManager = $objectManager;
    }
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $countryChoices = array();
        //by using result cache your query would be performed only once
        $countries = $this->objectManager
             ->getRepository('GeoQuizzGameBundle:Country')
             ->createQueryBuilder('c')
             ->orderBy('c.nameEn', 'ASC')
             ->getQuery()
             ->useResultCache(true)
             ->getResult();
        foreach($countries as $country) {
            $countryChoices[$country->getId()] = $country->getNameEn();
        }
        $builder
             ->add('country','choice',array(
                'choices' => $countryChoices,
                'label' => 'Country',
               ))
        ;
    } 
}

您还需要开始像调用服务一样调用您的表单