Лучший способ отфильтровать Symfony Form CollectionType - PullRequest
0 голосов
/ 03 августа 2020

Краткое знакомство с моими сущностями:

У меня две сущности. «Пользователь» и «Хронометраж». «Пользователь» может иметь много «хронометража».

Я хочу создать форму, в которой пользователь может редактировать свои хронометражи на ежедневной основе. Поэтому мне нужно фильтровать хронометраж по дням. Как лучше всего это сделать?

Я мог бы добавить отношения OneToMany в свою сущность «Пользователь» следующим образом:

/**
 * @ORM\OneToMany(targetEntity=Timekeeping::class, mappedBy="user")
 */
private $timekeepings;

А затем отфильтровать их в моем FormType, что я не совершенно уверен, как это сделать. Но если я go, то таким образом Doctrine получит все «хронометраж» для этого пользователя. Я хотел бы, если возможно, выполнить фильтрацию на уровне базы данных, поэтому из базы данных будут извлекаться только интересующие меня «хронометражи». Например, сегодняшняя дата.

Еще одно решение, о котором я подумал, - это добавить не отображаемое поле в мой FormType и заполнить его вручную.

$builder->add('timekeepings', CollectionType::class, [
    'entry_type' => TimekeepingType::class,
    'mapped' => false,
])

Я мог бы использовать репозиторий, чтобы получить хронометраж интерес. Но я не уверен, как назначить их моей форме "хронометраж". А позже извлеките их, чтобы сохранить изменения в базе данных.

EDIT: Александр предложил использовать query_builder, о котором я изначально думал, но, к сожалению, нет query_builder для CollectionType

1 Ответ

0 голосов
/ 06 августа 2020

Хорошо, вот как я это решил:

В моем контроллере я извлекаю интересующие хронометражи из моего репозитория и передаю их в свою форму через параметры формы.

$timekeepingsProject = $this->getDoctrine()
    ->getRepository(TimekeepingProject::class)
    ->findByUserAndYearAndMonthAndDay($user, $year, $month, $day);

$form = $this->createForm(TimekeepingUserType::class, $timekeepingUser, [
    'timekeepingsProject' => $timekeepingsProject,
]);

Затем в своей форме я добавляю неотмеченное поле этого типа. Затем данные поля заполняются предоставленной опцией в FormEvent 'POST_SET_DATA':

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        // omitted fields...
        ->add('timekeepingsProject', CollectionType::class, [
            'entry_type' => TimekeepingProjectType::class,
            'allow_add' => true,
            'allow_delete' => true,
            'required' => false,
            'mapped' => false,
            'label' => false,
        ]);
    
    $builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) use($options) {
        $form = $event->getForm();
        $form->get('timekeepingsProject')->setData($options['timekeepingsProject']);
    });
}

Убедитесь, что опция установлена ​​как требуется в форме:

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

Наконец мой контроллер обрабатывает сохранение / удаление объекта timekeepingsProject из базы данных. Это необходимо сделать, потому что поле помечено как несопоставленное и поэтому автоматически не сохраняется в базе данных. Доступ к несопоставленным полям можно получить следующим образом:

$form['timekeepingsProject']->getData()
...