Symfony Form - 带选择的问题(测验)

问题描述 投票:0回答:1

我正在尝试创建用于测验的 Symfony 表单,其中每个问题都有问题和选择(请参阅实体代码)。我有

RequestQuestion
实体,其中包含
description, isActive, choices
。选择是另一个实体,包含
name, correct
relation
来提问。最后
Request
包含 ManyToMany 选择(表示用户勾选了此选项)。

但现在我有问题,我需要以某种方式通过问题对选择进行分组(使用具有多个和扩展 true 的 EntityType)。不 - EntityType 的 group_by 不适用于 multiple = Expanded = true。这仅适用于选择框。

后来我添加了

Request
Question
的关系。这解决了一半的问题 - 我现在可以在 FormType 中将 CollectionType 添加到问题中(这是另一个 FormType
RequestQuestionType
)。 请注意,这会在数据库中产生冗余,这是不好的。(实际上并非如此。我不知道哪些问题用于此请求,因为问题可以通过设置
isActive
或添加新问题及时更改) 。但现在的问题是在
RequestQuestionType
我无法添加答案,因为问题没有这种关系(只有
Request
QuestionChoice
)。

问题是我怎样才能将答案填入这个表格中?我无法使用父项(

RequestFormType
),因为我无法按问题对选择进行分组,并且在问题中(
RequestQuestionType
)我无法添加关系。下面我发送代码的当前状态。

请求

    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

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

    /**
     * @ORM\ManyToOne(targetEntity=User::class, inversedBy="requests")
     * @ORM\JoinColumn(nullable=false)
     */
    private $User;

    /**
     * @ORM\Column(type="datetime")
     */
    private $created;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    private $resolved;

    /**
     * @ORM\ManyToOne(targetEntity=User::class)
     */
    private $resolvedBy;

    /**
     * @ORM\Column(type="string", length=32)
     */
    private $state;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $address;

    /**
     * @ORM\ManyToMany(targetEntity=RequestQuestion::class, inversedBy="requests")
     */
    private $questions;

    /**
     * @ORM\ManyToMany(targetEntity=RequestQuestionChoice::class, inversedBy="scholarRequestsAnswers")
     */
    private $answers;

请求问题

    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="text")
     */
    private $description;

    /**
     * @ORM\Column(type="boolean")
     */
    private $isActive;

    /**
     * @ORM\OneToMany(targetEntity=RequestQuestionChoice::class, mappedBy="Question", orphanRemoval=true)
     */
    private $choices;

    /**
     * @ORM\ManyToMany(targetEntity=Request::class, mappedBy="questions")
     */
    private $requests;

请求问题选择

    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $name;

    /**
     * @ORM\Column(type="boolean")
     */
    private $correct;

    /**
     * @ORM\ManyToOne(targetEntity=RequestQuestion::class, inversedBy="choices")
     * @ORM\JoinColumn(nullable=false)
     */
    private $Question;

请求表单类型

class RequestFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('address', TextType::class, [
                'constraints' => [
                    new NotBlank([
                        'message' => "Zadejte adresu"
                    ])
                ]
            ])
            ->add('questions', CollectionType::class, [
                'entry_type' => RequestQuestionType::class,
                'entry_options' => [
                    'questions' => $builder->getData()->getQuestions()
                ]
            ])
            ->add('tos', CheckboxType::class, [
                'mapped' => false,
                'value' => false,
                'constraints' => [
                    new IsTrue([
                        'message' => "Musíte souhlasit s našimi podmínkami použití"
                    ])
                ]
            ])
            ->add('Submit', SubmitType::class)
        ;
    }

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

请求问题类型

class RequestQuestionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $index = str_replace(["[", "]"], "", $builder->getPropertyPath());

        $builder
            ->add('???', EntityType::class, [
                'class' => RequestQuestionChoice::class,
                'choice_label' => 'name',
                'choices' => $options["questions"][$index]->getChoices(),
                'expanded' => true,
                'multiple' => true
            ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'questions' => []
        ]);
    }
}

注意:由于某种原因,来自

RequestFormType
的问题不会作为数据传递(data = null),所以这就是我将它们作为 Entry_options 传递的原因。但在
RequestQuestionType
中,它调用它的次数与问题数一样多,所以这有点奇怪,但我设法通过entry_otpions解决它并使用propertyPath中的索引。

注意:请求是使用虚拟数据 - 问题预先构建的,并传递到此表单。

注意:我之前也尝试过在用户勾选或不勾选选项时将 Request - RequestChoice 中的多对多关系分解为带有 bool 的 RequestAnwer 并预先生成 QuestionChoices 的所有答案。但是按问题对选择进行分组的问题也存在,所以我也无法让它发挥作用。

php symfony symfony-forms
1个回答
0
投票

解决了。

我添加了

RequestQuestionAnswers
,它具有 OneToMany 到
RequestQuestion
RequestQuestionAnswers
有一个问题),答案为 ManyToMany 到
RequestQuestionChoice
。这样,这个新实体就与问题 1:1 绑定,对于每个问题,我可以单独为每个问题生成 EntityType 并生成问题的选择。

如果有人遇到类似的问题,我将在此处粘贴最终代码。这个问题也非常有帮助:Create quizz form symfony

注意:遗憾的是我不能将其用于多个 false,因为

RequestQuestion.requestAnswers
是 Collection,因此它会抛出错误:
Entity of type "Doctrine\Common\Collections\ArrayCollection" passed to the choice field must be managed. Maybe you forget to persist it in the entity manager?

请求表单类型

class RequestFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('address', TextType::class, [
                'constraints' => [
                    new NotBlank([
                        'message' => "Zadejte adresu"
                    ])
                ],
            ])
            ->add('requestAnswers', CollectionType::class, [
                'entry_type' => RequestQuestionType::class,
                'entry_options' => [
                    'request' => $builder->getData(),
                    'label_attr' => [
                        'class' => 'd-none'
                    ]
                ],
                'label' => 'Dotazník'
            ])
            ->add('tos', CheckboxType::class, [
                'mapped' => false,
                'value' => false,
                'constraints' => [
                    new IsTrue([
                        'message' => "Musíte souhlasit s našimi podmínkami použití"
                    ])
                ],
                'label' => 'Souhlasím s podmínkami použití'
            ])
            ->add('Submit', SubmitType::class, [
                'label' => 'Odeslat'
            ])
        ;
    }

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

请求问题类型

class RequestQuestionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $index = str_replace(["[", "]"], "", $builder->getPropertyPath());
        /** @var RequestAnswers $answers */
        $answers = $options["request"]->getRequestAnswers()[$index];

        $builder
            ->add('selectedChoices', EntityType::class, [
                'class' => RequestQuestionChoice::class,
                'choices' => $answers->getQuestion()->getChoices(),
                'choice_label' => 'name',
                'label' => $answers->getQuestion()->getDescription(),
                'expanded' => true,
                'multiple' => true
            ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => RequestAnswers::class,
            'request' => null
        ]);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.