私は現在、多くのユーザー フィールド (+/- 80) を処理する必要があるプロジェクトに取り組んでいます。私の最初のアプローチは、ユーザー テーブルを 4 つのテーブル (主な情報、管理情報、銀行情報、統計情報) に垂直に分割することでした (今でもそうです)。3 つの余分なテーブル行の ID は、メイン テーブルの自動インクリメント ID を参照します。
私の質問は次のとおりです。
- そうすることは適切ですか?
- 私が関連付けを行った方法では、Doctrine は 1 つのオブジェクトを一度にデータベースにフラッシュすることができないようです:
タイプ MyVendor\User\UserBundle\Entity\UsersInfosBank のエンティティには、フィールド 'id_user' に割り当てられた ID がありません。このエンティティの識別子生成戦略では、EntityManager#persist() が呼び出される前に ID フィールドに入力する必要があります。代わりに自動生成された識別子が必要な場合は、それに応じてメタデータ マッピングを調整する必要があります。
プロジェクトは 3 週間で本番環境に移行されるため、これらのデータを 1 つの巨大なテーブルに格納する従来の方法に戻ることができます…
****************アップデート*****************
以下のコード全体のロジック*****************
私の問題に関係のないプロパティとメソッドのほとんどを削除しました…</p>
はい、私は FOSUserBundle を使用しています ;)
ユーザーメイン
<?php
namespace LCP\User\UserBundle\Entity;
use FOS\UserBundle\Model\GroupableInterface;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* UsersMain
*
* @ORM\Table(name="lcp_users_main")
* @ORM\Entity
*/
class UsersMain extends BaseUser
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
*
* @ORM\OneToOne(targetEntity="LCP\User\UserBundle\Entity\UsersInfosBank", mappedBy="id_user", cascade={"persist"})
*/
private $infosBank;
/**
*
* @ORM\OneToOne(targetEntity="LCP\User\UserBundle\Entity\UsersApodis", mappedBy="id_user", cascade={"persist"})
*/
private $apodis;
/**
*
* @ORM\OneToOne(targetEntity="LCP\User\UserBundle\Entity\UsersInfosAdmin", mappedBy="id_user", cascade={"persist"})
*/
private $infosAdmin;
/**
*
* @ORM\OneToOne(targetEntity="LCP\User\UserBundle\Entity\UsersInfosStats", mappedBy="id_user", cascade={"persist"})
*/
private $infosStats;
/**
* Constructor
*/
public function __construct()
{
$this->groups = new \Doctrine\Common\Collections\ArrayCollection();
$this->creationDate = new \Datetime();
}
/**
* Set apodis
*
* @param \LCP\User\UserBundle\Entity\UsersApodis $apodis
* @return UsersMain
*/
public function setApodis(\LCP\User\UserBundle\Entity\UsersApodis $apodis = null)
{
if(is_null($this->apodis) && is_null($apodis)){
$this->apodis = new \LCP\User\UserBundle\Entity\UsersApodis();
} else {
$this->apodis = $infosBank;
}
$this->apodis->setIdUser($this);
return $this;
}
/**
* Get apodis
*
* @return \LCP\User\UserBundle\Entity\UsersApodis
*/
public function getApodis()
{
if(is_null($this->infosAdmin)){
$this->infosAdmin = new \LCP\User\UserBundle\Entity\UsersApodis();
}
return $this->apodis;
}
/**
* Set infosAdmin
*
* @param \LCP\User\UserBundle\Entity\UsersInfosAdmin $infosAdmin
* @return UsersMain
*/
public function setInfosAdmin(\LCP\User\UserBundle\Entity\UsersInfosAdmin $infosAdmin = null)
{
if(is_null($this->infosAdmin) && is_null($infosAdmin)){
$this->infosAdmin = new \LCP\User\UserBundle\Entity\UsersInfosAdmin();
} else {
$this->infosAdmin = $infosAdmin;
}
$this->infosAdmin->setIdUser($this);
return $this;
}
/**
* Get infosAdmin
*
* @return \LCP\User\UserBundle\Entity\UsersInfosAdmin
*/
public function getInfosAdmin()
{
if(is_null($this->infosAdmin)){
$this->infosAdmin = new \LCP\User\UserBundle\Entity\UsersInfosAdmin();
}
return $this->infosAdmin;
}
/**
* Set infosStats
*
* @param \LCP\User\UserBundle\Entity\UsersInfosStats $infosStats
* @return UsersMain
*/
public function setInfosStats(\LCP\User\UserBundle\Entity\UsersInfosStats $infosStats = null)
{
if(is_null($this->infosStats) && is_null($infosStats)){
$this->infosStats = new \LCP\User\UserBundle\Entity\UsersInfosStats();
} else {
$this->infosStats = $infosAdmin;
}
$this->infosStats->setIdUser($this);
return $this;
}
/**
* Get infosStats
*
* @return \LCP\User\UserBundle\Entity\UsersInfosStats
*/
public function getInfosStats()
{
if(is_null($this->infosStats)){
$this->infosStats = new \LCP\User\UserBundle\Entity\UsersInfosStats();
}
return $this->infosStats;
}
}
ユーザー情報管理者
<?php
namespace LCP\User\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* UsersInfosAdmin
*
* @ORM\Table(name="lcp_users_infos_admin", indexes={@ORM\Index(name="pharmacyCip_idx", columns={"pharmacy_cip"})})
* @ORM\Entity
*/
class UsersInfosAdmin
{
/**
* @var integer
* @ORM\Id
* @ORM\OneToOne(targetEntity="LCP\User\UserBundle\Entity\UsersMain", cascade={"persist"}, inversedBy="infosAdmin")
*/
private $id_user;
/**
* Set id_user
*
* @param \LCP\User\UserBundle\Entity\UsersMain $idUser
* @return UsersInfosAdmin
*/
public function setIdUser(\LCP\User\UserBundle\Entity\UsersMain $idUser)
{
$this->id_user = $idUser;
return $this;
}
/**
* Get id_user
*
* @return \LCP\User\UserBundle\Entity\UsersMain
*/
public function getIdUser()
{
return $this->id_user;
}
}
ユーザー情報統計
<?php
namespace LCP\User\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* UsersInfosStats
*
* @ORM\Table(name="lcp_users_infos_stats")
* @ORM\Entity
*/
class UsersInfosStats
{
/**
* @var integer
* @ORM\Id
* @ORM\OneToOne(targetEntity="LCP\User\UserBundle\Entity\UsersMain", cascade={"persist"}, inversedBy="infosStats")
*/
private $id_user;
/**
* Set id_user
*
* @param \LCP\User\UserBundle\Entity\UsersMain $idUser
* @return UsersInfosStats
*/
public function setIdUser(\LCP\User\UserBundle\Entity\UsersMain $idUser)
{
$this->id_user = $idUser;
return $this;
}
/**
* Get id_user
*
* @return \LCP\User\UserBundle\Entity\UsersMain
*/
public function getIdUser()
{
return $this->id_user;
}
}
ユーザーを作成する方法は次のとおりです(安全な管理エリアフォームを使用します):
/**
* This action get the field from the form
*/
public function userSaveAction(Request $request)
{
$userManager = $this->get('fos_user.user_manager');
$this->request = $request;
$userValues = $this->getRequest()->request->all();
$this->em = $this->getDoctrine()->getManager();
$user = $this->processUser($userValues);
$userManager->updateUser($user, false);
return $this->redirect($this->generateUrl('lcp_admin_user_edit', ['id'=>$user->getId()]));
}
/**
* This method process user fields and uses setters (or getters for joined entities) to set datas of user
*/
private function processUser($userValues)
{
if($userValues['userId']=="") {
$user = $this->get('fos_user.user_manager')->createUser();
} else {
$user = $this->em->getRepository('LCPUserBundle:UsersMain')
->findOneBy(['id' => $userId]);
}
//construction of related entities
$user->setInfosAdmin();
$user->setInfosBank();
$user->setInfosStats();
$user->setApodis();
unset($userValues['userId']);
//this method inspect submitted field to check if they are mandatory or if current user is allowed to modify them
$this->fields = $this->getInfosFields();
foreach($userValues as $input=>$value){
list($entity,$input)=explode('-',$input);
if($input=='plainPassword' && $value==''){
continue;
}
if($entity=='Main'){
$setter = 'set'.ucfirst($input);
$user->$setter($value);
} else {
$setter = 'set'.ucfirst($input);
$join = 'get'.$entity;
$user->$join()->$setter($value);
}
}
return $user;
}