Использовать query_builder на CollectionType в формах symfony4? - PullRequest
0 голосов
/ 19 декабря 2018

В форме Symfony 4 мне нужно использовать что-то вроде опции query_builder, которая доступна на EntityType, но на CollectionType.Здесь есть похожий вопрос здесь без хороших ответов.

В моем проекте каждая Site сущность имеет множество Goal.Каждый Goal имеет числовую цель и конкретную дату.Я хочу редактировать цели сайта только на конкретную дату.Проблема заключается в том, что форма CollectionType извлекает все целей для отображения в форме, но я хочу получить только цели на определенную дату.Как?На CollectionType нет query_builder, как на EntityType.Я мог бы изменить геттер в моем объекте Site, но я не знаю, как передать нужную дату моему геттеру.

На данный момент мой обходной путь - это рендеринг всей формы (со ВСЕМИ связанными целями длязаданный сайт), а затем используйте JavaScript, чтобы скрыть все цели, кроме тех, которые имеют дату для редактирования.Это работает, но это ужасное решение для сайтов с множеством целей, охватывающих несколько дат.

Моя Site сущность (отображается только соответствующий код):

class Site
{
    public function __construct()
    {
        $this->goals = new ArrayCollection();
    }

    /** @ORM\OneToMany(targetEntity="App\Entity\Goal", mappedBy="site") */
    private $goals;


    public function getGoals()
    {
        return $this->goals;
    }
}

и моясвязанные Goal сущности:

class Goal
{
    /** @ORM\Column(type="date") */
    private $goalDate;

    /** @ORM\Column(type="integer") */
    private $goal;

    /** @ORM\ManyToOne(targetEntity="App\Entity\Site", inversedBy="goals") */
    private $site;

    // ...
}

Мои формы:

class SiteGoalsAdminForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('goals', CollectionType::class, [
                'entry_type' => GoalsEmbeddedForm::class,
            ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Site::class
        ]);
    }
}

и форма индивидуальной цели:

class GoalsEmbeddedForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('goal', IntegerType::class)
            ->add('goalDate', DateType::class);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Goal::class,
        ]);
    }
}

1 Ответ

0 голосов
/ 27 декабря 2018

Используя События формы , избегая при этом параметров allow_add и allow_delete для формы CollectionType, вы можете оказаться в правильном соседстве:

Во-первых, давайте предположим, что мы фильтруем по году, для простоты примера, и что год вычленяется из стиля строки запроса ?y=2018.Мы передадим эту информацию в конструктор форм:

<?php
// Inside a *Action method of a controller

public function index(Request $request): Response
{
    // ...
    $filteredYear = $request->get('y');
    $form         = $this->createForm(SiteGoalsAdminForm::class, $site, ['year_filter' => $filteredYear]);
    // ...
}

Это означает, что мы должны обновить параметры по умолчанию для класса SiteGoalsAdminForm:

<?php

// SiteGoalsAdminForm.php

// ...
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
          'data_class' => Site::class,
          'year_filter' => 2018
        ]);
     }
// ...

Затем вbuildForm метод того же класса, мы могли бы получить доступ к объекту Site и удалить Goals из него, если год goalDate не попадал в

<?php

// SiteGoalsAdminForm.php

namespace App\Form;

// ... other `use` statements, plus:
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

class SiteGoalsAdminForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (FormEvent $event) use ($options) {
                $form = $event->getForm();
                /** @var Site */
                $site  = $event->getData();
                $goals = $site->getGoals();

                foreach ($goals as $g) {
                    if ($g->getGoalDate()->format('Y') !== (string) $options['year_filter']) {
                        $site->removeGoal($g);
                    }
                }

                $form->add('goals', CollectionType::class, [
                    'entry_type' => GoalsEmbeddedForm::class,
                ]);
            }
        );
    }

    // ...
}

формы.но функционально схожий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...