Search code examples
symfonysymfony-2.6

Entity choice list in FormType isn't sending values


I have the following code in my FormType:

/**
 * @var User
 */
protected $currentUser;

/**
 * param User $currentUser
 */
public function __construct($currentUser)
{
    $this->currentUser = $currentUser;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{   
    $currentUser = $this->currentUser;

    $builder
        ->add('breedingPairMale', 'entity', array(
            'class' => 'Breedr\GeckoBundle\Entity\Gecko',
            'property' => 'id',
            'property' => 'name',
            'placeholder' => 'Choose a Male',
            'query_builder' => function(EntityRepository $er) use ($currentUser) {
                return $er->createQueryBuilder('g')
                    ->where('g.user = :currentUser')
                    ->andWhere('g.sex = :sex')
                    ->orderBy('g.name')
                    ->setParameter('currentUser', $currentUser)
                    ->setParameter('sex', 'Male');
            }
        ))
        ->add('breedingPairFemale', 'entity', array(
            'class' => 'Breedr\GeckoBundle\Entity\Gecko',
            'property' => 'id',
            'property' => 'name',
            'placeholder' => 'Choose a Female',
            'query_builder' => function(EntityRepository $er) use ($currentUser) {
                return $er->createQueryBuilder('g')
                    ->where('g.user = :currentUser')
                    ->andWhere('g.sex = :sex')
                    ->orderBy('g.name')
                    ->setParameter('currentUser', $currentUser)
                    ->setParameter('sex', 'Female');
            }
        ))
        ->add('breedingPairDate')
        ->add('breedingPairSeason')
    ;
}

Which builds the select boxes absolutely fine, and when i inspect the element i see the value is the gecko's ID and the Name is also visible, so it's all good.

It submits the form correctly too:

public function createAction(Request $request)
{
    $entity = new Pairs();
    $form = $this->createCreateForm($entity);
    $form->handleRequest($request);

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

        return $this->redirect($this->generateUrl('pairs_show', array('id' => $entity->getId())));
    }

    return $this->render('BreedrBreedingPairsBundle:Pairs:new.html.twig', array(
        'entity' => $entity,
        'form'   => $form->createView(),
    ));
}

/**
 * Creates a form to create a Pairs entity.
 *
 * @param Pairs $entity The entity
 *
 * @return \Symfony\Component\Form\Form The form
 */
private function createCreateForm(Pairs $entity)
{
    $currentUser = $this->getUser()->getId();

    $form = $this->createForm(new PairsType($currentUser), $entity, array(
        'action' => $this->generateUrl('pairs_create'),
        'method' => 'POST',
    ));

    $form->add('submit', 'submit', array('label' => 'Create'));

    return $form;
}

... However, when it saves it to the database, the values in the database table for the male and female are 0's

This is my id from the Gecko class:

/**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

Do i need to make a ManyToOne relationship for this to work? Or am i missing something else?

Thanks in advance,

Andy

EDIT:

Pairs entity:

<?php

namespace Breedr\BreedingPairsBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Pairs
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class Pairs
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var integer
     *
     * @ORM\Column(name="breeding_pair_male", type="integer")
     */
    private $breedingPairMale;

    /**
     * @var integer
     *
     * @ORM\Column(name="breeding_pair_female", type="integer")
     */
    private $breedingPairFemale;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="breeding_pair_date", type="date")
     */
    private $breedingPairDate;

    /**
     * @var integer
     *
     * @ORM\Column(name="breeding_pair_season", type="integer")
     */
    private $breedingPairSeason;


    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set id
     *
     * @return Pairs 
     */
    public function setId($id)
    {
        $this->id = $id;

        return $this;
    }

    /**
     * Set breedingPairMale
     *
     * @param integer $breedingPairMale
     * @return Pairs
     */
    public function setBreedingPairMale($breedingPairMale)
    {
        $this->breedingPairMale = $breedingPairMale;

        return $this;
    }

    /**
     * Get breedingPairMale
     *
     * @return integer 
     */
    public function getBreedingPairMale()
    {
        return $this->breedingPairMale;
    }

    /**
     * Set breedingPairFemale
     *
     * @param integer $breedingPairFemale
     * @return Pairs
     */
    public function setBreedingPairFemale($breedingPairFemale)
    {
        $this->breedingPairFemale = $breedingPairFemale;

        return $this;
    }

    /**
     * Get breedingPairFemale
     *
     * @return integer 
     */
    public function getBreedingPairFemale()
    {
        return $this->breedingPairFemale;
    }

    /**
     * Set breedingPairDate
     *
     * @param \DateTime $breedingPairDate
     * @return Pairs
     */
    public function setBreedingPairDate($breedingPairDate)
    {
        $this->breedingPairDate = $breedingPairDate;

        return $this;
    }

    /**
     * Get breedingPairDate
     *
     * @return \DateTime 
     */
    public function getBreedingPairDate()
    {
        return $this->breedingPairDate;
    }

    /**
     * Set breedingPairSeason
     *
     * @param integer $breedingPairSeason
     * @return Pairs
     */
    public function setBreedingPairSeason($breedingPairSeason)
    {
        $this->breedingPairSeason = $breedingPairSeason;

        return $this;
    }

    /**
     * Get breedingPairSeason
     *
     * @return integer 
     */
    public function getBreedingPairSeason()
    {
        return $this->breedingPairSeason;
    }
}

Gecko entity:

<?php

namespace Breedr\GeckoBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;

/**
 * Gecko
 *
 * @ORM\Table()
 * @ORM\Entity
 * @Vich\Uploadable
 */
class Gecko
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

    /**
     * @ORM\OneToMany(targetEntity="Weight", mappedBy="geckoId", cascade={"persist", "remove"})
    */
    private $weights;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="aquisition_date", type="date")
     */
    private $aquisitionDate;

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

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

    /**
     * @var string
     *
     * @ORM\Column(name="genetics", type="text")
     */
    private $genetics;

    /**
     * @var string
     *
     * @ORM\Column(name="bio", type="text")
     */
    private $bio;

    /**
     * @var boolean
     *
     * @ORM\Column(name="bred", type="boolean")
     */
    private $bred;

    /**
     * @var boolean
     *
     * @ORM\Column(name="hatchling", type="boolean")
     */
    private $hatchling;

    /**
     * @var integer
     *
     * @ORM\Column(name="clutch", type="integer")
     */
    private $clutch;

    /**
     * NOTE: This is not a mapped field of entity metadata, just a simple property.
     * 
     * @Vich\UploadableField(mapping="gecko_image", fileNameProperty="imageName")
     * 
     * @var File $imageFile
     */
    protected $imageFile;

    /**
     * @ORM\Column(type="string", length=255, name="image_name")
     *
     * @var string $imageName
     */
    protected $imageName;

    /**
     * @ORM\Column(type="datetime")
     *
     * @var \DateTime $updatedAt
     */
    protected $updatedAt;

    /**
     * @ORM\ManyToOne(targetEntity="Breedr\UserBundle\Entity\User", inversedBy="geckos")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     */
    protected $user;

    /**
     * If manually uploading a file (i.e. not using Symfony Form) ensure an instance
     * of 'UploadedFile' is injected into this setter to trigger the  update. If this
     * bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
     * must be able to accept an instance of 'File' as the bundle will inject one here
     * during Doctrine hydration.
     *
     * @param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
     */
    public function setImageFile(File $image = null)
    {
        $this->imageFile = $image;

        if ($image) {
            // It is required that at least one field changes if you are using doctrine
            // otherwise the event listeners won't be called and the file is lost
            $this->updatedAt = new \DateTime('now');
        }
    }

    /**
     * @return File
     */
    public function getImageFile()
    {
        return $this->imageFile;
    }

    /**
     * @param string $imageName
     */
    public function setImageName($imageName)
    {
        $this->imageName = $imageName;
    }

    /**
     * @return string
     */
    public function getImageName()
    {
        return $this->imageName;
    }

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

    public function __toString(){
        return $this->name;
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Gecko
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set aquisitionDate
     *
     * @param \DateTime $aquisitionDate
     * @return Gecko
     */
    public function setAquisitionDate($aquisitionDate)
    {
        $this->aquisitionDate = $aquisitionDate;

        return $this;
    }

    /**
     * Get aquisitionDate
     *
     * @return \DateTime 
     */
    public function getAquisitionDate()
    {
        return $this->aquisitionDate;
    }

    /**
     * Set morph
     *
     * @param string $morph
     * @return Gecko
     */
    public function setMorph($morph)
    {
        $this->morph = $morph;

        return $this;
    }

    /**
     * Get morph
     *
     * @return string 
     */
    public function getMorph()
    {
        return $this->morph;
    }

    /**
     * Set sex
     *
     * @param string $sex
     * @return Gecko
     */
    public function setSex($sex)
    {
        $this->sex = $sex;

        return $this;
    }

    /**
     * Get sex
     *
     * @return string 
     */
    public function getSex()
    {
        return $this->sex;
    }

    /**
     * Set genetics
     *
     * @param string $genetics
     * @return Gecko
     */
    public function setGenetics($genetics)
    {
        $this->genetics = $genetics;

        return $this;
    }

    /**
     * Get genetics
     *
     * @return string 
     */
    public function getGenetics()
    {
        return $this->genetics;
    }

    /**
     * Set bio
     *
     * @param string $bio
     * @return Gecko
     */
    public function setBio($bio)
    {
        $this->bio = $bio;

        return $this;
    }

    /**
     * Get bio
     *
     * @return string 
     */
    public function getBio()
    {
        return $this->bio;
    }

    /**
     * Set bred
     *
     * @param boolean $bred
     * @return Gecko
     */
    public function setBred($bred)
    {
        $this->bred = $bred;

        return $this;
    }

    /**
     * Get bred
     *
     * @return boolean 
     */
    public function getBred()
    {
        return $this->bred;
    }

    /**
     * Set hatchling
     *
     * @param boolean $hatchling
     * @return Gecko
     */
    public function setHatchling($hatchling)
    {
        $this->hatchling = $hatchling;

        return $this;
    }

    /**
     * Get hatchling
     *
     * @return boolean 
     */
    public function getHatchling()
    {
        return $this->hatchling;
    }

    /**
     * Set clutch
     *
     * @param integer $clutch
     * @return Gecko
     */
    public function setClutch($clutch)
    {
        $this->clutch = $clutch;

        return $this;
    }

    /**
     * Get clutch
     *
     * @return integer 
     */
    public function getClutch()
    {
        return $this->clutch;
    }

    /**
     * Set photo
     *
     * @param string $photo
     * @return Gecko
     */
    public function setPhoto($photo)
    {
        $this->photo = $photo;

        return $this;
    }

    /**
     * Get photo
     *
     * @return string 
     */
    public function getPhoto()
    {
        return $this->photo;
    }


    /**
     * Set updatedAt
     *
     * @param \DateTime $updatedAt
     * @return Gecko
     */
    public function setUpdatedAt($updatedAt)
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }

    /**
     * Get updatedAt
     *
     * @return \DateTime 
     */
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }

    /**
     * Add weights
     *
     * @param \Breedr\GeckoBundle\Entity\Weight $weights
     * @return Gecko
     */
    public function addWeight(\Breedr\GeckoBundle\Entity\Weight $weights)
    {
        $this->weights[] = $weights;

        return $this;
    }

    /**
     * Remove weights
     *
     * @param \Breedr\GeckoBundle\Entity\Weight $weights
     */
    public function removeWeight(\Breedr\GeckoBundle\Entity\Weight $weights)
    {
        $this->weights->removeElement($weights);
    }

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

    /**
     * Set user
     *
     * @param \Breedr\UserBundle\Entity\User $user
     * @return Gecko
     */
    public function setUser(\Breedr\UserBundle\Entity\User $user = null)
    {
        $this->user = $user;

        return $this;
    }

    /**
     * Get user
     *
     * @return \Breedr\UserBundle\Entity\User 
     */
    public function getUser()
    {
        return $this->user;
    }
}

Solution

  • Ok, what I belevie is happening here is the mismatch of data types.

    • Your form tells that data type is entity (of Gecko)
    • Your entity, having @Column annotation, tells it's simple type

    After Request is handled, everything seems find - Gecko entities have been assigned to $breedingPairMale and $breedingPairFemale. However, when it comes to persisting I am surprised that it didn't break. I am curious why.

    To fix this, you need to fix (or, in fact, create) relations in your Pairs entity:

    class Pairs
    {
        // ................
        // ................
        // ................
    
        /**
         * @var Breedr\GeckoBundle\Entity\Gecko
         *
         * @ORM\ManyToOne(targetEntity="Breedr\GeckoBundle\Entity\Gecko")
         * @ORM\JoinColumn(name="breeding_pair_male", referencedColumnName="id")
         */
        private $breedingPairMale;
    
        /**
         * @var Breedr\GeckoBundle\Entity\Gecko
         *
         * @ORM\ManyToOne(targetEntity="Breedr\GeckoBundle\Entity\Gecko")
         * @ORM\JoinColumn(name="breeding_pair_female", referencedColumnName="id")
         */
        private $breedingPairFemale;
    
        // ................
        // ................
        // ................
    

    Now, $breedingPairMale and $breedingPairFemale are no longer of type integer but rather class Gecko and persisting it should work.