Как прикрепить объект с аргументами в collectionType? - PullRequest
0 голосов
/ 10 февраля 2019

Мне нужно управлять ответами на форму в моем проекте Symfony.В настоящее время у меня есть 4 объекта:

  • MyForm представляет глобальную форму
  • QuestionsBlock представляет блок вопросов
  • Вопрос представляет вопрос
  • ModelQuestion представляет значение вопроса по умолчанию

В моем классе MyFormType у меня есть атрибут CollectionType типа QuestionsBlockType.Действительно, я хотел бы динамически добавлять / удалять блоки вопросов в моей форме.Но каждый блок вопросов должен содержать вопросы, основанные на объектах типовых вопросов.

Например, если в моей базе данных есть 5 записей questionModel, я хочу, чтобы каждый раз при добавлении блока вопросов создавалось 5 новых вопросов.Когда я передаю вопросы в конструкторе QuestionsBlock, я пытаюсь создавать новый экземпляр QuestionsBlock с параметром каждый раз, когда в CollectionType создается новая запись.

Чтобы добиться этого, я увидел в документе, что яможет использовать атрибут prototype_data для CollectionType: https://symfony.com/doc/current/reference/forms/types/collection.html#prototype-data

При использовании этой опции дочерние типы отображаются на экране, но, похоже, объекты не создаются при отправке формы.

Итак, я увидел, что могу использовать атрибут empty_data в QuestionBlockType для создания экземпляра с параметром: https://symfony.com/doc/current/form/use_empty_data.html

Но, похоже, этого недостаточно.Я знаю, что «код empty_data» выполняется, когда я сохраняю форму, но у меня появляется ошибка «Слишком мало аргументов для функции Question :: __ construct (), 0 передано и ожидается ровно 1».Поэтому я предполагаю, что конструктор QuestionsBlock вызывается при отправке, но я не могу понять, почему он пытается создать экземпляр Question без аргументов.

Что мне делать?

Контроллер

public function addAction(Request $request)
{
    $em = $this->getDoctrine()->getManager();
    $models = $em->getRepository(QuestionModel::class)->findAll();
    $myForm = new MyForm();

    $form = $this->createForm(MyFormType::class, $myForm, ['models' => $models]);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $em->persist($myForm);
        $em->flush();

        return $this->redirectToRoute('...');
    }

    return $this->render('Admin/MyForm/add_edit.html.twig', array(
        'myForm' => $myForm,
        'models' => $models,
        'form'   => $form->createView()
    ));
}

MyForm Entity

/**
 * MyForm
 *
 * @ORM\Table(name="my_form")
 * @ORM\Entity()
 */
class MyForm
{
    /**
     * @ORM\OneToMany(targetEntity="QuestionsBlock", mappedBy="myForm", cascade={"persist", "remove"})
     */
    private $questionsBlocks;

    ...
}

QuestionBlocks Entity

/**
 * QuestionsBlock
 *
 * @ORM\Table(name="questions_block")
 * @ORM\Entity()
 */
class QuestionsBlock
{
    /**
     * @ORM\OneToMany(targetEntity="question", mappedBy="questionsBlock", cascade={"persist", "remove"})
     */
    private $questions;

    public function __construct($models)
    {
        $this->questions = new ArrayCollection();

        foreach ($models as $model) {
            $this->addQuestion(new Question($model));
        }
    }

    ...
}

Вопрос Entity

/**
 * Question
 *
 * @ORM\Table(name="question")
 * @ORM\Entity()
 */
class Question
{
    /**
     * @ORM\ManyToOne(targetEntity="ModelQuestion")
     */
    private $modelQuestion;

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

    ...
}

MyForm Type

class MyFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $models = $options['models'];

        $builder
            ->add('questionsBlocks', CollectionType::class, array(
                'entry_type'     => QuestionsBlockType::class,
                'required'       => true,
                'allow_add'      => true,
                'allow_delete'   => true,
                'delete_empty'   => true,
                'by_reference'   => false,
                'prototype_data' => (new QuestionBlock($models))
            ))
            ->add('save', SubmitType::class, array(
                'label' => 'Enregistrer'
            ))
        ;
    }

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

QuestionsBlock Type

class QuestionsBlockType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('questions', CollectionType::class, array(
                'entry_type'   => QuestionType::class,
                'required'     => true,
                'allow_add'    => true,
                'allow_delete' => true,
                'delete_empty' => true,
                'by_reference' => false
            ))
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'empty_data' => function (FormInterface $form) {
                return new QuestionsBlock($form->getRoot()->getConfig()->getOption('models'));
            },
            'data_class' => QuestionsBlock::class
        ));
    }
}

Тип вопроса

class QuestionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title', TextType::class, array(
                'label'    => 'Titre',
                'required' => false
            ))
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Question::class
        ));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...