减少Symfony2形式的请求数量

时间:2014-07-16 17:59:15

标签: php forms symfony

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

第一种表格类型:

<?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()
    ));
}

我有124个字段的请求,因为国家/地区列表在每一行都是重新查询,是否有防止它的解决方案?

我可以在控制器中执行查询并将我的国家/地区数组作为表单类型的参数传递,是否干净?

1 个答案:

答案 0 :(得分:1)

您可以使用choice字段类型而不是entity。您需要做的只是choices参数,其中包含您的国家/地区列表。

$countryChoices是一个国家/地区的关联数组,您可以抓取一次并在buildForm方法中使用它。我这样做的方法是将表单作为服务,并将ObjectManager传递给contructor:

<强> 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',
               ))
        ;
    } 
}

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