Search code examples
symfonysymfony-formssymfony-components

Symfony2: Inserting collection form data


There is a one-to-one relationship between User and Company entity.
When initializing (creating) the user's company, userID should be bind to Company user field as a foreign key. But instead of that, i get this error message:

Property "id" is not public in class "Website\CompanyBundle\Entity\User". Maybe you should create the method "setId()"?

Why Symfony wants to create new User when this form is about Company entity, and User entity is just a collection that should provide user's ID.

Here is my code:

Company.php entity:

namespace Website\CompanyBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity(repositoryClass="Website\CompanyBundle\Entity\Repository\CompanyRepository")
 * @ORM\Table(name="company")
 */
class Company
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\OneToOne(targetEntity="User", inversedBy="company")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     */
    protected $user;

    /**
     * @ORM\Column(type="string")
     */
    protected $name;

}


CompanyType.php

class CompanyType extends AbstractType
{
    private $security;
    public function __construct(SecurityContext $security)
    {
        $this->security= $security;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $user = $this->securityContext->getToken()->getUser();

        $builder
        ->add('user', new UserType($security))
        ->add('company_name')
        ->add('company_address')
        ...
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Website\CompanyBundle\Entity\Company'
        ));
    }

    public function getName()
    {
        return 'user';
    }
}


UserRelationType.php

class UserRelationType extends AbstractType
{
    private $user;

    public function __construct(SecurityContext $security){
        $this->user = $security->getToken()->getUser();
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('id', 'hidden', array('data' => $this->user->getId()))
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Website\CompanyBundle\Entity\User'
        ));
    }

    public function getName()
    {
        return 'user';
    }
}


User.php entity

namespace Website\CompanyBundle\Entity;

use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="fos_user")
 */
class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    protected $name;

    /**
     * @ORM\OneToOne(targetEntity="Company", mappedBy="user")
     */
    protected $company;
}

Solution

  • You map entity to form in UserRelationType. On save it try to set id on user entity. You must specify data transformer or use entity type if you need to select existed user.

    If you want to set current user, better do it in event listener like pre_persist