2015-04-20 75 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); 
    } 
} 

我相信(我希望)有更好的方法,但我期待聽到他們的聲音,因爲這僅僅是工作的事爲了我。

我希望它有幫助。

問候, 哈維爾