Belkacem Yahiaoui
Belkacem Yahiaoui

Reputation: 61

foreign key null in collection form symfony 3

i have two entities Survey.php and Choice.php I create a form to add new survey and multi choices, I used a many-to-one relation between the two entities, the problem is when I submit for a new survey, the foreign key of choice entity return null

here's my code

Survey.PHP

/**
 * Survey
 *
 * @ORM\Table(name="survey")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\SurveyRepository")
 */
class Survey
{
 /....  

    /**
     * @var ArrayCollection
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Choice", mappedBy="survey_id",cascade="persist")
     * @ORM\JoinColumn(nullable=false, referencedColumnName="id")
     */
    private $choice;

    public function __construct()
    {
        $this->choice = new ArrayCollection();
    }



    /**
     * Add choice
     *
     * @param \AppBundle\Entity\Choice $choice
     *
     * @return Survey
     */
    public function addChoice(\AppBundle\Entity\Choice $choice)
    {
        $this->choice[] = $choice;
        $choice->setSurvey($this);
        return $this;
    }

    /**
     * Remove choice
     *
     * @param \AppBundle\Entity\Choice $choice
     */
    public function removeChoice(\AppBundle\Entity\Choice $choice)
    {
        $this->choice->removeElement($choice);
    }

    /**
     * Get choice
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getChoice()
    {
        return $this->choice;
    }
}

Choice.php

/**
 * Choice
 * @ORM\Table(name="choice")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\ChoiceRepository")
 */
class Choice
{

    /**
     * @var int
     * @ORM\ManyToOne(targetEntity="Survey",inversedBy="choice")
     */
    private $survey;



    /**
     * Set survey
     *
     * @param \AppBundle\Entity\Survey $survey
     *
     * @return Choice
     */
    public function setSurveyId(\AppBundle\Entity\Survey $survey)
    {
        $this->survey = $survey;

        return $this;
    }

    /**
     * Get surveyId
     *
     * @return \AppBundle\Entity\Survey
     */
    public function getSurveyId()
    {
        return $this->survey_id;
    }
}

SurveyController.php

<?php

namespace AppBundle\Controller;

use AppBundle\Entity\Survey;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

/**
 * Survey controller.
 *
 */
class SurveyController extends Controller
{

    /**
     * Creates a new survey entity.
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function newAction(Request $request)
    {
        $survey = new Survey();
        //
        $form = $this->createForm('AppBundle\Form\SurveyType', $survey);
        $form->handleRequest($request);
        $survey->setCreateDate(new \DateTime('NOW'));

        if ($form->isSubmitted() && $form->isValid()) {
                $em = $this->getDoctrine()->getManager();
                $em->persist($survey);
                $em->flush();


                return $this->redirectToRoute('survey_show', ['id' => $survey->getId()]);
            }


        return $this->render('survey/new.html.twig', [
            'survey' => $survey,
            'form' => $form->createView(),
        ]);
    }

any suggestion, btw I think the problem is in the getters and setters )

Upvotes: 1

Views: 778

Answers (3)

Franck Theeten
Franck Theeten

Reputation: 140

It worked with me, but I had to remove the explicit foreign key mapping with the "inversedBy" setting from the class definition. I use a composite foreign key (using two columns), which maybe makes things harder though...

Upvotes: 0

Belkacem Yahiaoui
Belkacem Yahiaoui

Reputation: 61

I fixed the problem by adding a for each loop inside the SurveyController.php and it works just fine

SurveyController.php

if ($form->isSubmitted() && $form->isValid())
        {
            foreach ($survey->getChoices() as $choice){
                $choice->setSurvey($survey);
            }

            $em = $this->getDoctrine()->getManager();
            $em->persist($survey);
            $em->flush();

not "THE best solution" but it gets the job done

Upvotes: 1

Cerad
Cerad

Reputation: 48865

Link the choice to the survey:

// Survey
public function addChoice(\AppBundle\Entity\Choice $choice)
{
    $this->choice[] = $choice;
    $choice->setSurvey($this);
    return $this;
}

And change the survey_id stuff to survey. Dealing with objects not ids. And of course Survey::choice should be Survey::choices. The name changes might seem minor but will make your easier to maintain.

Upvotes: 1

Related Questions