2015-04-20 71 views
0

我有两个实体:UserCompanyInfo使用Symfony2格式更新两个实体共享主键

两者之间的关系是oneToOne,所述User可以具有零个或一个CompanyInfo,和一个CompanyInfo属于一个User

所以我设置它们具有相同的主键(用户ID):

class User extends BaseUser 
{ 
/** 
* @ORM\Id 
* @ORM\Column(type="integer") 
* @ORM\GeneratedValue(strategy="AUTO") 
*/ 
protected $id; 
/** 
* @ORM\OneToOne(targetEntity="CompanyInfo", mappedBy="user", cascade={"persist"}) 
* @var CompanyInfo 
*/ 
protected $companyInfo; 
... 
} 

class CompanyInfo 
{ 

/** 
* @ORM\OneToOne(targetEntity="User", inversedBy="companyInfo", cascade={"persist"}) 
* @ORM\JoinColumn(name="user_id", referencedColumnName="id") 
* @ORM\Id 
* @var User 
*/ 
protected $user; 
.... 
} 

我有一个问题,试图在同一时间揭露他们,使他们可以只提交更新一种形式:

在UserFormType我有以下线:

$builder->add('companyInfo', new CompanyInfoFormType(), ['required' => false, 'by_reference' => false]) 

CompanyInfoFormType有以下几点:

/** 
* @param OptionsResolverInterface $resolver 
*/ 
public function setDefaultOptions(OptionsResolverInterface $resolver) 
{ 
    $resolver->setDefaults(array(
     'data_class' => '....\Entity\CompanyInfo', 
     'intention' => 'registration' 
    )); 
} 

它一切正常,表单与用户和公司信息字段都呈现。当创建一个新用户&公司信息,但只能是因为我做了在UserFormHandleronSuccess以下(排在首位基本上坚持了User,看起来有点hackie,但无法找到一个更好的办法):

if ($user->getCompanyInfo() instanceof CompanyInfo) { 
     $companyInfo = $user->getCompanyInfo()->setUser($user); 
     $user->setCompanyInfo(null); 
     $this->entityManager->beginTransaction(); 
     $this->entityManager->persist($user); 
     $this->entityManager->flush(); 
     $this->entityManager->persist($companyInfo); 
     $this->entityManager->flush(); 
     $this->entityManager->commit(); 
     $this->entityManager->refresh($user); 
    } 

现在,问题是当我试图更新已有companyInfo的用户时。出于某种奇怪的原因,学说认为CompanyInfo实体不存在,它试图做INSERT而不是UPDATE。这就好像实体CompanyInfo它不是由Doctrine管理的,因此当级联持续时,试图创建一个新的。

有没有人遇到同样的问题?任何想法将非常感激!

感谢, 哈维尔

+0

为什么要卸下公司'$用户> setCompanyInfo从用户实体(空)'我想这就是教义的原因是创建新的 –

+0

只需用户ID添加到该公司,反之亦然。放弃保持主键同步的尝试。这只会造成下游问题。 – Cerad

+0

Khalid这段代码只在POST上执行,不会在PUT或PATCH上运行,所以它必须是别的东西。我将它设置为null,否则级联坚持不起作用,因为两个实体具有相同的PK –

回答

0

我终于设法找到了一个解决方案,它的效果并不理想,虽然,但它的工作原理。基本上,我UpdateFormHandlerprocess方法看起来像如下:

/** 
* @param UserInterface $user 
* @return bool 
*/ 
public function process(UserInterface $user) 
{ 
    $this->form->setData($user); 

    $method = $this->request->getMethod(); 
    if (in_array($method, ['PUT', 'PATCH'])) { 
     $this->form->submit($this->request, 'PATCH' !== $method); 

     if ($this->form->isValid()) { 
      /** @var User $user */ 
      $this->saveCompanyInfo($user); 
      $this->onSuccess($user); 
      $this->userManager->reloadUser($user); 
      return true; 
     } 
    } 

    return false; 
} 

/** 
* Create link companyInfo -> User when persisting CompanyInfo for first time 
* 
* @param User $user 
*/ 
protected function saveCompanyInfo(User $user) 
{ 
    if ($user->getCompanyInfo() instanceof CompanyInfo && !$user->getCompanyInfo()->getUser()) { 

     $user->getCompanyInfo()->setUser($user); 

    } elseif ($user->getCompanyInfo() instanceof CompanyInfo) { 
     /** 
     * If companyInfo exists and has been modified, doctrine things that it's a new entity 
     * detached from the manager, and will try to insert a new row on the company_info table (which crashes, as the PK (user_id) already exists). 
     * By calling ->merge, we obtain an attached/managed instance, 
     * so that it will be properly cascade persisted when the user is saved. 
     */ 
     /** @var CompanyInfo $companyInfo */ 
     $companyInfo = $this->getEntityManager()->merge($user->getCompanyInfo()); 
     $user->setCompanyInfo($companyInfo); 
    } 
} 

我相信(我希望)有更好的方法,但我期待听到他们的声音,因为这仅仅是工作的事为了我。

我希望它有帮助。

问候, 哈维尔