Symfony2 表单更新一对一关系

Symfony2 form update one-to-one relation

我需要有关 Symfony2 表单一对一关系更新的帮助。我必须实体:User 和 UserInfo

用户实体:

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

    /**
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Group")
     * @ORM\JoinTable(name="fos_user_user_group",
     *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id")}
     * )
     */
    protected $groups;

    /**
     * @ORM\OneToOne(targetEntity="UserInfo", mappedBy="user", cascade={"all"})
     */
    private $info;

    /**
     * @ORM\OneToMany(targetEntity="Log", mappedBy="user")
     */
    private $logs;

    public function __construct()
    {
        parent::__construct();
        $this->logs = new ArrayCollection();
    }

    /**
     * Set info
     *
     * @param \AppBundle\Entity\UserInfo $info
     * @return User
     */
    public function setInfo(\AppBundle\Entity\UserInfo $info = null)
    {
        $this->info = $info;
        $info->setUser($this);

        return $this;
    }

    /**
     * Get info
     *
     * @return \AppBundle\Entity\UserInfo 
     */
    public function getInfo()
    {
        return $this->info;
    }

    /**
     * Add logs
     *
     * @param \AppBundle\Entity\Log $logs
     * @return User
     */
    public function addLog(\AppBundle\Entity\Log $logs)
    {
        $this->logs[] = $logs;

        return $this;
    }

    /**
     * Remove logs
     *
     * @param \AppBundle\Entity\Log $logs
     */
    public function removeLog(\AppBundle\Entity\Log $logs)
    {
        $this->logs->removeElement($logs);
    }

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

用户信息实体:

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

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

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

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

    /**
     * @ORM\OneToOne(targetEntity="User", inversedBy="info")
     */
    private $user;

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

    /**
     * Set position
     *
     * @param string $position
     * @return UserInfo
     */
    public function setPosition($position)
    {
        $this->position = $position;

        return $this;
    }

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

    /**
     * Set info
     *
     * @param string $info
     * @return UserInfo
     */
    public function setInfo($info)
    {
        $this->info = $info;

        return $this;
    }

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

    /**
     * Set fullname
     *
     * @param string $fullname
     * @return UserInfo
     */
    public function setFullname($fullname)
    {
        $this->fullname = $fullname;

        return $this;
    }

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

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

        return $this;
    }

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

这些是它们的类型:

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('username')
            ->add('email')
            ->add('password')
            ->add('info', new UserInfoType(), [
                'by_reference' => false,
            ])
            ->add('Submit', 'submit')
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'AppBundle\Entity\User',
        ]);
    }

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

class UserInfoType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('position')
            ->add('info')
            ->add('fullname')
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'AppBundle\Entity\UserInfo',
            'allow_delete' => true,
        ]);
    }

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

新记录插入没有任何问题,但是当我想用这个动作更新这条记录时:

public function editAction(Request $request, $id)
{
    $em = $this->getDoctrine()->getManager();

    $userRepository = $em->getRepository('AppBundle:User');

    $user = $userRepository->findOneBy(['id' => $id]);

    $form = $this->createForm(new UserType(), $user);

    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $em->persist($user);
        $em->flush();

        return $this->redirectToRoute('user_list');
    }

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

我收到这个错误:

An exception occurred while executing 'INSERT INTO user_info (position, info, fullname, user_id) VALUES (?, ?, ?, ?)' with params ["321", "321", "321", 14]:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '14' for key 'UNIQ_B1087D9EA76ED395'

好的,我知道他想插入新记录,但我应该怎么做才能让他更新记录或删除现有记录并插入新记录。

您需要在 User class:

中使用 JoinColumn 注释
/**
 * @ORM\OneToOne(targetEntity="UserInfo", inversedBy="user", cascade={"all"})
 * @ORM\JoinColumn(name="info", referencedColumnName="id")
 */
private $info;

用户信息:

/**
* @ORM\OneToOne(targetEntity="User", mappedBy="info")
*/
private $user;

尝试将 User 设为拥有方,将 UserInfo 设为相反方(参见 docs)。

class User extends BaseUser
{
    /**
     * @ORM\OneToOne(targetEntity="UserInfo", inversedBy="user", cascade={"all"})
     */
    private $info;
}

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

/**
  * @ORM\OneToOne(targetEntity="User", mappedBy="info")
  */
    private $user;
}

也与this SO question有关。

编辑: 要在更新后删除旧的、未引用的 UserInfo 记录,请在 info [=30] 中设置 orphanRemoval 选项=] User class.

class User extends BaseUser
{
    /**
     * @ORM\OneToOne(targetEntity="UserInfo", inversedBy="user", cascade={"all"}, orphanRemoval=true)
     */
    private $info;
}