Search code examples
phpsymfonyadminsonata-admin

Cannot get related entity field to save in Symfony Admin Form


I'm working my way through Symfony trying to learn how it all fits together and I'm working on the admin section.

Right now I'm putting together an admin form for a Show Entity which will reference a section entity (so this show belongs in that section, etc). Every other field in the form saves EXCEPT for the related entity choice field.

This is the ShowAdmin class

 <?php

namespace AppBundle\Admin;

use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Nelmio\ApiDocBundle\Tests\Fixtures\Form\EntityType;

class ShowAdmin extends AbstractAdmin {
    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper->add('title', 'text')
                   ->add('shortname', 'text')
                   ->add('section_id', EntityType::class, array(
                        'class' => 'AppBundle:SectionEntity',
                        'choice_label' => 'section_title',
                   ))
                   ->add('logo', 'text')
                   ->add('description', 'textarea')
                   ->add('status', 'integer');
    }

    protected function configureDatagridFilters(DatagridMapper $datagridMapper)
    {
        $datagridMapper->add('title');
        $datagridMapper->add('shortname');
    }

    protected function configureListFields(ListMapper $listMapper)
    {
        $listMapper->addIdentifier('title');
        $listMapper->add('shortname', 'text');
    }
}

This is the ShowEntity

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="shows")
 */
class ShowEntity {

    function __construct() {
        $this->children = new \Doctrine\Common\Collections\ArrayCollection();
    }


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

   /**
    * @ORM\Column(type="string", length=100)
    */
   private $title;

   /**
    * @ORM\Column(type="string", length=100)
    */
   private $shortname;

   /**
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\SectionEntity")
    */
   private $section;

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

   /**
    * @ORM\Column(type="text")
    */
   private $description;

   /**
    * @ORM\Column(type="integer")
    */
   private $status;


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

    /**
     * Set title
     *
     * @param string $title
     *
     * @return ShowEntity
     */
    public function setTitle($title)
    {
        $this->title = $title;

        return $this;
    }

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

    /**
     * Set sectionId
     *
     * @param integer $sectionId
     *
     * @return ShowEntity
     */
    public function setSectionId($sectionId)
    {
        $this->section_id = $sectionId;

        return $this;
    }

    /**
     * Get sectionId
     *
     * @return integer
     */
    public function getSectionId()
    {
        return $this->section_id;
    }

    /**
     * Set logo
     *
     * @param string $logo
     *
     * @return ShowEntity
     */
    public function setLogo($logo)
    {
        $this->logo = $logo;

        return $this;
    }

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

    /**
     * Set description
     *
     * @param string $description
     *
     * @return ShowEntity
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

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

    /**
     * Set status
     *
     * @param integer $status
     *
     * @return ShowEntity
     */
    public function setStatus($status)
    {
        $this->status = $status;

        return $this;
    }

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

    /**
     * Set shortname
     *
     * @param string $shortname
     *
     * @return ShowEntity
     */
    public function setShortname($shortname)
    {
        $this->shortname = $shortname;

        return $this;
    }

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

And this is the SectionEntity

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * SectionEntity
 *
 * @ORM\Table(name="section_entity")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\SectionEntityRepository")
 */
class SectionEntity
{

    protected $section_id;

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

    /**
     * @ORM\Column(type="text")
     */
    private $section_title;

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

    /**
     * Set sectionTitle
     *
     * @param string $sectionTitle
     *
     * @return SectionEntity
     */
    public function setSectionTitle($sectionTitle)
    {
        $this->section_title = $sectionTitle;

        return $this;
    }

    /**
     * Get sectionTitle
     *
     * @return string
     */
    public function getSectionTitle()
    {
        return $this->section_title;
    }

    /**
     * Get string
     */
    public function __toString() {
        return $this->section_title;
    }

    function __construct() {
        $this->section_id = new \Doctrine\Common\Collections\ArrayCollection();
    }

}

Any help would be greatly appreciated, I know it's probably something super simple that I'm just not seeing.

Thanks.


Solution

    1. (optional) Rename ShowEntity::$section into ShowEntity::$sections to highlight sections is a collection but not a single entity.
    2. Set ShowEntity __construct method body to:

      $this->sections = new \Doctrine\Common\Collections\ArrayCollection();
      
    3. At ShowAdmin::configureFormFields rename

      ->add('section_id', EntityType::class, array(
      

      into

      ->add('section', EntityType::class, array(
      

      You should use direct reference to the relation instead of id.

    4. Remove SectionEntity::__construct method, it has no sense.
    5. Remove protected $section_id; from SectionEntity.
    6. Change public function setSectionId($sectionId) into public function setSection(Section $section).
    7. Perhaps you also need to rename section_title into sectionTitle or simply title, not sure about that.