представлять коллекцию как одно множественное поле

1

У меня есть объект Alert, который может содержать несколько объектов. Категория:

  /**
     * @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;

у меня нет никаких проблем с созданием и сохранением моего объекта, но когда я хочу редактировать, у меня проблема с представлением. Я хочу показать весь существующий объект Category, прикрепленный к моему Alert, в выбранном поле:

Изображение 174551

но в настоящее время он отображает выбранное поле для каждого прикрепленного объекта:

Изображение 174551

Итак, если у вас есть 100 категорий в этом объекте Alert, у меня будет поле выбора категории 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, представленной как коллекция. И если использовать ai:

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

у меня будет тот, кто сказал, что symfony ждет коллекцию и получит категорию.

благодаря

  • 0
    Я не уверен, правильно ли я понимаю. Вы хотите, чтобы при редактировании Alert отображались только выбранные категории (уважительно выбирайте только те, которые находятся в БД)?
  • 0
    @tftd Точно, когда я редактирую, я хочу выбрать поле со всей выбранной категорией
Теги:
entity-framework
formbuilder

2 ответа

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

конечно, я должен установить set getter и setter типа Category в Alert Entity.

Кто-нибудь знает, имеет ли этот способ низкую производительность? Я просто переписываю метод, который используется SF, поэтому я не думаю.

Надеюсь, это поможет другим людям

0

В вашем случае, я обычно передать параметр, такие как $alertId = null вашего AlertType. Позже, при инициализации вашего CategoryType я тоже передал бы эту переменную. Затем в вашем buildForm 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 и вы должны быть сделаны.

  • 0
    проблема с этим методом в том, что я получу только прикрепленную категорию для текущего оповещения. Я хочу получить всю существующую категорию и предварительно проверить текущую выбранную. Это мое плохо, я скучаю, понял ваш прецедент
  • 0
    А ну понятно. В этом случае вам придется сделать это в шаблоне twig . Обычно я создаю собственный шаблон ветки для конкретного поля Symfony Doc . Я мог бы показать вам более подходящий пример кода позже.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню