将集合实体表示为一个多个字段

时间:2015-08-29 11:16:18

标签: php entity-framework symfony formbuilder

我有一个实体警报,可以包含多个实体类别:

  /**
     * @ORM\ManyToMany(targetEntity="MDB\AnnonceBundle\Entity\Category")
     * @ORM\JoinTable(name="alerts_categories",
     *      joinColumns={@ORM\JoinColumn(name="alert_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="cateory_id", referencedColumnName="id")}
     *      )
     * */
    private $categories;

我没有关于我的实体的创建和持久性的探测但是当我想编辑时我有一个表示问题。我想在选定的字段中显示附加到我的警报的所有当前类别实体,如:

enter image description here

但目前它为每个附加的实体显示一个选定的字段:

enter image description here

因此,如果此警报实体中有100个类别,我将有100个类别选择字段。我想要的只是预先检查现有类别的那个。

  

AlertType.php   

class AlertType extends AbstractType {

    public function __construct() {

    }

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
                ->remove('user')
                ->remove('date')
                ->add('itemsToFind', 'collection')
                ->add("categories", "collection", array("type" => new CategoryType(true, true)))
                ->add('lieu')
                ->add("regions", "collection", array("type" => new RegionType()))
                ->add('fullCountry', 'checkbox', array(
                    'label' => 'Créer une alerte pour toute la France ?',
                    'required' => false,
                ))
        ;
    }

    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults(array(
            'data_class' => 'MDB\UserBundle\Entity\Alert'
        ));
    }

    /**
     * @return string
     */
    public function getName() {
        return 'mdb_userbundle_alert';
    }

}
  

CategoryType.php。

<?php


class CategoryType extends AbstractType {

    public function __construct($multiple, $mapped) {
        $this->multiple = $multiple;
        $this->mapped=$mapped;
    }


    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
                ->add('category', 'entity', array(
                    'class' => 'MDBAnnonceBundle:Category',
                    'required' => true,
                    'choice_label' => 'nom',
                    'multiple' => $this->multiple,
                    'mapped' => $this->mapped,
                    'label' => false,
                    'attr' => array('class' => 'multiple categoriesToControl'),
                    'query_builder' => function(CategoryRepository $cr) {
                        return $cr->findAllOrderedByName();
                    }

        ));
    }

   public function configureOptions(OptionsResolver  $resolver) {
        $resolver->setDefaults(array(
            'data_class' => 'MDB\AnnonceBundle\Entity\Category'
        ));
    }


    public function getName() {
        return 'mdb_annoncebundle_category';
    }

}

我知道这是正常的原因,在alertType类别中表示为集合。如果我使用:

 ->add('categories', new CategoryType(false, true))  

我会有一个人说symfony正在等待收集并获得一个类别。

由于

2 个答案:

答案 0 :(得分:0)

在您的情况下,我通常会将$alertId = null等参数传递给您的AlertType。稍后,在初始化CategoryType时,我也会传递该变量。然后,在CategoryType方法的buildForm中,我会根据$alertId值执行查询。

将我的话放在代码中:

class AlertType extends AbstractType {

    private $alertId;

    public function __construct($alertId = null) {
        $this->alertId = $alertId;
    }

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
            ->remove('user')
            ->remove('date')
            ->add('itemsToFind', 'collection')
            ->add(
                "categories",
                "collection",
                array(
                    "type" => new CategoryType(
                        $this->alertId, true, true
                    )
                )
            )
            ->add('lieu')
            ->add("regions", "collection", array("type" => new RegionType()))
            ->add(
                'fullCountry',
                'checkbox',
                array(
                    'label' => 'Créer une alerte pour toute la France ?',
                    'required' => false,
                )
            );
    }

    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults(
            array(
                'data_class' => 'MDB\UserBundle\Entity\Alert'
            )
        );
    }

    /**
     * @return string
     */
    public function getName() {
        return 'mdb_userbundle_alert';
    }
}
class CategoryType extends AbstractType {

    private $alertId;

    public function __construct($alertId = null, $multiple, $mapped) {
        $this->multiple = $multiple;
        $this->mapped = $mapped;
        $this->alertId = $alertId;
    }


    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
            ->add('category', 'entity', array(
                'class' => 'MDBAnnonceBundle:Category',
                'required' => true,
                'choice_label' => 'nom',
                'multiple' => $this->multiple,
                'mapped' => $this->mapped,
                'label' => false,
                'attr' => array('class' => 'multiple categoriesToControl'),
                'query_builder' => function(CategoryRepository $cr) {
                    if(!$this->alertId) {
                        return $cr->findAllOrderedByName();
                    } else {
                        return $cr->findAllOrderedByNameForAlertId($alertId);
                    }
                }

            ));
    }

    public function configureOptions(OptionsResolver  $resolver) {
        $resolver->setDefaults(array('data_class' => 'MDB\AnnonceBundle\Entity\Category'));
    }

    public function getName() {
        return 'mdb_annoncebundle_category';
    }

}

现在在您的CategoryRepository中创建一个名为findAllOrderedByNameForAlertId的方法,该方法会返回Alert的特定选定结果,您应该完成。

答案 1 :(得分:0)

我找到了解决方案,

以前我在我的控制器中使用它来编辑我的警报:

$form = $this->createForm(new AlertType(), $alert);

由于SF直接加载了持久集合并导致错误。现在我用这个:

$form = $this->createForm(new AlertType($alert));

我手动保持该字段。

if ($form->handleRequest($request)->isValid()) {

            $em = $this->getDoctrine()->getManager();

            $alert->setItemsToFind($form->get('itemsToFind')->getData());
            $alert->setLieu($form->get('lieu')->getData());
            $alert->setfullCountry($form->get('fullCountry')->getData());
            $em->persist($alert);
            $em->flush();

            return $this->redirect($this->generateUrl('my_alerts'));
        }

对于表单类型,我现在使用它:

class AlertType extends AbstractType {

    public function __construct($alert = null) {
        $this->alert = $alert;
    }

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
                ->remove('user')
                ->remove('date')
                ->add('itemsToFind', 'text', array('data' => $this->alert->getItemsToFind()))
                ->add('categories', new CategoryType(true, true, $this->alert))
                ->add('lieu', 'text', array('data' => $this->alert->getLieu()))
                ->add('regions', new RegionType($this->alert->getRegions()))
                ->add('fullCountry', 'checkbox', array(
                    'label' => 'Créer une alerte pour toute la France ?',
                    'data' => $this->alert->getFullCountry()
                ))
        ;
    }

这里是我的CategoryType的构建器:

 $builder
                ->add('category', 'entity', array(
                    'class' => 'MDBAnnonceBundle:Category',
                    'required' => true,
                    'choice_label' => 'nom',
                    'multiple' => $this->multiple,
                    'mapped' => $this->mapped,
                    'label' => false,
                    'attr' => array('class' => 'multiple categoriesToControl'),                  
                    'query_builder' => function(CategoryRepository $cr) {
                            return $cr->findAllOrderedByName();
                    },'data' => (!$this->alert)?(null):($this->alert->getCategories())
        ));
    }

当然我必须在Alert Entity中设置set getter和Category类型的setter。

有人知道这种方式是否性能低下?我只是重写了SF习惯使用的方法,所以我不认为。

希望这会有助于其他人