phpdatabaseformssymfonypersist

How do I persist my form to the database?


I need to persist my form to the database. I am using Symfony to do this and I have built a response entity:

<?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;
    }

A new response function in the ResponseController (please note QuizResponse is an alias of Response entity. This is to not confuse my response entity with 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,
        ]);
    }

A ResponseType form:

<?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,
        ]);
    }
}

And here is my twig template (_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) }}

It's completely detached from the responseType form which is why I believe it doesn't submit to the database... But I am not sure how to map the ResponseType form to the _form.html.twig


Solution

  • you dont use the form component - you have the class and the correct controller code, but in your template you print the form fields yourself.

    Just define the fields in your formType, remove the formfields from your twig and use the supposed {{ form_*() }} methods.

    To make this conditional rendering of your CollectionType work - you will have to write some twig code in your form theme. (but to explain this is outside of my time and scope of the question)