Symfony 表单 - 有选择的问题(测验)
Symfony Form - questions (quiz) with choices
我正在尝试为测验创建 Symfony 表单,其中包含问题和每个问题的选项(请参阅实体代码)。我有 RequestQuestion
个包含 description, isActive, choices
的实体。 Choices 是另一个包含 name, correct
和 relation
的实体来提问。最后 Request
包含 ManyToMany 选项(表示用户勾选了此选项)。
但现在我遇到了问题,我需要以某种方式在表单中按问题分组选择(将 EntityType 与 multiple 和 expanded true 结合使用)。不 - EntityType 的 group_by 不适用于 multiple = expanded = true。这仅适用于选择框。
后来我添加了 Request
与 Question
的关系。这解决了一半的问题——我现在可以在 FormType 中将 CollectionType 添加到问题中(这是另一个 FormType RequestQuestionType
)。 请注意,这会在数据库中产生冗余,这并不好。(实际上并不会。我不知道该请求使用了哪些问题,因为问题可以通过设置及时更改isActive
或添加新问题)。但现在的问题是 RequestQuestionType
我无法添加答案,因为问题没有这种关系(只有 Request
或 QuestionChoice
)。
问题是我怎样才能得到这个表格的答案?我不能使用 parrent (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;
RequestQuestionChoice
/**
* @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;
RequestFormType
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
]);
}
}
RequestQuestionType
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.[=31= 中的索引]
注意:请求是使用虚拟数据预先构建的 - 问题并传递给此表单。
注意:我之前也尝试过将 Request - RequestChoice 中的 manyToMany 关系分解为 RequestAnwer 和 bool,因为用户是否勾选了选择并预生成对 questionChoices 的所有答案。但是按问题对选项进行分组也存在问题,所以我也无法让它工作。
已解决。
我已经添加了 RequestQuestionAnswers
,其中有一对多到 RequestQuestion
(RequestQuestionAnswers
有一个问题)并且答案是多对多到 RequestQuestionChoice
。这样,这个新实体就绑定 1:1 到问题,对于每个问题,我可以单独为每个问题生成 EntityType 并生成问题的选择。
如果有人遇到类似问题,我将在此处粘贴最终代码。这个问题也很有帮助:
注意:遗憾的是我不能将它用于多个 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?
RequestFormType
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
]);
}
}
RequestQuestionType
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
]);
}
}
我正在尝试为测验创建 Symfony 表单,其中包含问题和每个问题的选项(请参阅实体代码)。我有 RequestQuestion
个包含 description, isActive, choices
的实体。 Choices 是另一个包含 name, correct
和 relation
的实体来提问。最后 Request
包含 ManyToMany 选项(表示用户勾选了此选项)。
但现在我遇到了问题,我需要以某种方式在表单中按问题分组选择(将 EntityType 与 multiple 和 expanded true 结合使用)。不 - EntityType 的 group_by 不适用于 multiple = expanded = true。这仅适用于选择框。
后来我添加了 Request
与 Question
的关系。这解决了一半的问题——我现在可以在 FormType 中将 CollectionType 添加到问题中(这是另一个 FormType RequestQuestionType
)。 请注意,这会在数据库中产生冗余,这并不好。(实际上并不会。我不知道该请求使用了哪些问题,因为问题可以通过设置及时更改isActive
或添加新问题)。但现在的问题是 RequestQuestionType
我无法添加答案,因为问题没有这种关系(只有 Request
或 QuestionChoice
)。
问题是我怎样才能得到这个表格的答案?我不能使用 parrent (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;
RequestQuestionChoice
/**
* @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;
RequestFormType
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
]);
}
}
RequestQuestionType
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.[=31= 中的索引]
注意:请求是使用虚拟数据预先构建的 - 问题并传递给此表单。
注意:我之前也尝试过将 Request - RequestChoice 中的 manyToMany 关系分解为 RequestAnwer 和 bool,因为用户是否勾选了选择并预生成对 questionChoices 的所有答案。但是按问题对选项进行分组也存在问题,所以我也无法让它工作。
已解决。
我已经添加了 RequestQuestionAnswers
,其中有一对多到 RequestQuestion
(RequestQuestionAnswers
有一个问题)并且答案是多对多到 RequestQuestionChoice
。这样,这个新实体就绑定 1:1 到问题,对于每个问题,我可以单独为每个问题生成 EntityType 并生成问题的选择。
如果有人遇到类似问题,我将在此处粘贴最终代码。这个问题也很有帮助:
注意:遗憾的是我不能将它用于多个 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?
RequestFormType
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
]);
}
}
RequestQuestionType
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
]);
}
}