如何将表单保存到数据库?
How do I persist my form to the database?
我需要将表单保存到数据库中。我正在使用 Symfony 来执行此操作,并且我已经构建了一个响应实体:
<?php
namespace App\Entity;
use App\Repository\ResponseRepository;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
use Symfony\Component\Validator\Constraints as Assert;
* )
* @ORM\Entity(repositoryClass=ResponseRepository::class)
*/
class Response
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(name="id", type="integer")
* @Groups({"response:read"})
*
*/
private $id;
/**
* @ORM\Column(name="answer", type="string", length=255)
* @Groups({"response:write", "response:read", "session:read"})
* @Assert\NotBlank()
*/
private $answer;
/**
* @ORM\ManyToOne(targetEntity=Session::class, inversedBy="responses")
* @ORM\JoinColumn(nullable=false)
* @Assert\Valid
*/
private $session;
/**
* @ORM\ManyToOne(targetEntity=Question::class, inversedBy="responses")
* @ORM\JoinColumn(nullable=false)
* @Groups({"response:read", "response:write"})
*/
private $question;
// /**
// * @ORM\OneToMany(targetEntity=QuestionsQuestionType::class, mappedBy="response")
// */
// private $questionsQuestionType;
public function __construct()
{
$this->questionsQuestionType = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getAnswer(): ?string
{
return $this->answer;
}
public function setAnswer(string $answer): self
{
$this->answer = $answer;
return $this;
}
public function getSession(): ?Session
{
return $this->session;
}
public function setSession(?Session $session): self
{
$this->session = $session;
return $this;
}
public function getQuestion(): ?Question
{
return $this->question;
}
public function setQuestion(?Question $question): self
{
$this->question = $question;
return $this;
}
ResponseController 中的新响应函数(请注意 QuizResponse 是 Response 实体的别名。这是为了不要将我的响应实体与 Symfony Response 混淆):
/**
* @Route("/new", name="response_new", methods={"GET", "POST"})
*/
public function new(Request $request, EntityManagerInterface $entityManager, QuestionRepository $questionRepository): Response
{
$questions = $questionRepository->findAll();
// dd($questions);
$response = new QuizResponse();
$form = $this->createForm(ResponseType::class, $response); // problem exists
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($response);
$entityManager->flush();
// $formData = $form->getData();
// dd($formData);
// echo 'this should work';exit;
return $this->redirectToRoute('response_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('response/new.html.twig', [
'response' => $response,
'question' => $questions,
'form' => $form,
]);
}
一个 ResponseType 表单:
<?php
namespace App\Form;
use App\Entity\Response;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class ResponseType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Response::class,
]);
}
}
这是我的树枝模板 (_form.html.twig):
{{ form_start(form) }}
<div class="mt-3">
{% for question in question %}
<input type="hidden" name="response[question][]" value="{{ question.id }}">
{% set name = 'response[answer]['~ question.id ~']' %}
{% if question.type == 'checkbox' %}
{% set name = name ~ '[]' %}
{% endif %}
{# {% if question.replies is defined %}#}
<div class="mb-3 mt-3 border">
<h3 class="mb-0" id="question-{{ question.id }}">{{ loop.index }}. {{ question.label }}</h3>
</div>
{% if question.type == 'checkbox' or question.type == 'radio' %}
<div class="answers p-1">
{% for answer in question.replies %}
{% set id = 'answer-' ~ answer.id %}
<label for="{{ id }}">{{ answer.answer }}</label>
<input type="{{ question.type }}" name="{{ name }}" id="{{ id }}">
{% endfor %}
</div>
{% elseif question.type == 'textarea' %}
<textarea name="{{ name }}" aria-labelledby="question-{{ question.id }}" cols="30" rows="5" class="form-control"></textarea>
{% elseif question.type == 'number' %}
<input type="number" name="{{ name }}" aria-labelledby="question-{{ question.id }}">
{% else %}
<input type="text" name="{{ name }}" aria-labelledby="question-{{ question.id }}" class="form-control">
{% endif %}
{# {% endif %}#}
{% endfor %}
</div>
<button class="btn btn-primary">{{ button_label|default('Submit') }}</button>
{#{{ form_end(form, {render_rest: false }) }}#}
{{ form_end(form) }}
它完全脱离了 responseType 表单,这就是我认为它不会提交到数据库的原因...但我不确定如何将 ResponseType 表单映射到 _form.html.twig
您没有使用表单组件 - 您有 class 和正确的控制器代码,但在您的模板中您自己打印表单字段。
只需在您的 formType 中定义字段,从您的 twig 中删除表单字段并使用假定的 {{ form_*() }}
方法。
要使 CollectionType 的这种有条件的呈现有效 - 您将必须在表单主题中编写一些 twig 代码。 (但解释这超出了我的时间和问题范围)
我需要将表单保存到数据库中。我正在使用 Symfony 来执行此操作,并且我已经构建了一个响应实体:
<?php
namespace App\Entity;
use App\Repository\ResponseRepository;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
use Symfony\Component\Validator\Constraints as Assert;
* )
* @ORM\Entity(repositoryClass=ResponseRepository::class)
*/
class Response
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(name="id", type="integer")
* @Groups({"response:read"})
*
*/
private $id;
/**
* @ORM\Column(name="answer", type="string", length=255)
* @Groups({"response:write", "response:read", "session:read"})
* @Assert\NotBlank()
*/
private $answer;
/**
* @ORM\ManyToOne(targetEntity=Session::class, inversedBy="responses")
* @ORM\JoinColumn(nullable=false)
* @Assert\Valid
*/
private $session;
/**
* @ORM\ManyToOne(targetEntity=Question::class, inversedBy="responses")
* @ORM\JoinColumn(nullable=false)
* @Groups({"response:read", "response:write"})
*/
private $question;
// /**
// * @ORM\OneToMany(targetEntity=QuestionsQuestionType::class, mappedBy="response")
// */
// private $questionsQuestionType;
public function __construct()
{
$this->questionsQuestionType = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getAnswer(): ?string
{
return $this->answer;
}
public function setAnswer(string $answer): self
{
$this->answer = $answer;
return $this;
}
public function getSession(): ?Session
{
return $this->session;
}
public function setSession(?Session $session): self
{
$this->session = $session;
return $this;
}
public function getQuestion(): ?Question
{
return $this->question;
}
public function setQuestion(?Question $question): self
{
$this->question = $question;
return $this;
}
ResponseController 中的新响应函数(请注意 QuizResponse 是 Response 实体的别名。这是为了不要将我的响应实体与 Symfony Response 混淆):
/**
* @Route("/new", name="response_new", methods={"GET", "POST"})
*/
public function new(Request $request, EntityManagerInterface $entityManager, QuestionRepository $questionRepository): Response
{
$questions = $questionRepository->findAll();
// dd($questions);
$response = new QuizResponse();
$form = $this->createForm(ResponseType::class, $response); // problem exists
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($response);
$entityManager->flush();
// $formData = $form->getData();
// dd($formData);
// echo 'this should work';exit;
return $this->redirectToRoute('response_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('response/new.html.twig', [
'response' => $response,
'question' => $questions,
'form' => $form,
]);
}
一个 ResponseType 表单:
<?php
namespace App\Form;
use App\Entity\Response;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class ResponseType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Response::class,
]);
}
}
这是我的树枝模板 (_form.html.twig):
{{ form_start(form) }}
<div class="mt-3">
{% for question in question %}
<input type="hidden" name="response[question][]" value="{{ question.id }}">
{% set name = 'response[answer]['~ question.id ~']' %}
{% if question.type == 'checkbox' %}
{% set name = name ~ '[]' %}
{% endif %}
{# {% if question.replies is defined %}#}
<div class="mb-3 mt-3 border">
<h3 class="mb-0" id="question-{{ question.id }}">{{ loop.index }}. {{ question.label }}</h3>
</div>
{% if question.type == 'checkbox' or question.type == 'radio' %}
<div class="answers p-1">
{% for answer in question.replies %}
{% set id = 'answer-' ~ answer.id %}
<label for="{{ id }}">{{ answer.answer }}</label>
<input type="{{ question.type }}" name="{{ name }}" id="{{ id }}">
{% endfor %}
</div>
{% elseif question.type == 'textarea' %}
<textarea name="{{ name }}" aria-labelledby="question-{{ question.id }}" cols="30" rows="5" class="form-control"></textarea>
{% elseif question.type == 'number' %}
<input type="number" name="{{ name }}" aria-labelledby="question-{{ question.id }}">
{% else %}
<input type="text" name="{{ name }}" aria-labelledby="question-{{ question.id }}" class="form-control">
{% endif %}
{# {% endif %}#}
{% endfor %}
</div>
<button class="btn btn-primary">{{ button_label|default('Submit') }}</button>
{#{{ form_end(form, {render_rest: false }) }}#}
{{ form_end(form) }}
它完全脱离了 responseType 表单,这就是我认为它不会提交到数据库的原因...但我不确定如何将 ResponseType 表单映射到 _form.html.twig
您没有使用表单组件 - 您有 class 和正确的控制器代码,但在您的模板中您自己打印表单字段。
只需在您的 formType 中定义字段,从您的 twig 中删除表单字段并使用假定的 {{ form_*() }}
方法。
要使 CollectionType 的这种有条件的呈现有效 - 您将必须在表单主题中编写一些 twig 代码。 (但解释这超出了我的时间和问题范围)