我目前正在处理一个项目,我必须处理很多用户字段(+/- 80)。我的第一种方法是(现在仍然是)将用户表垂直划分为 4 个表:主要信息、管理信息、银行信息、统计信息。3 个额外表行的 id 是指主表的自动递增 id。
我的问题是:
- 这样做是否相关?
- 看起来,通过我进行关联的方式,Doctrine 无法一次性将一个对象刷新到数据库中:
MyVendor\User\UserBundle\Entity\UsersInfosBank 类型的实体缺少为字段“id_user”分配的 ID。此实体的标识符生成策略要求在调用 EntityManager#persist() 之前填充 ID 字段。如果您想要自动生成标识符,则需要相应地调整元数据映射。
该项目将在 3 周内投入生产,因此我们仍然能够回到更传统的方式将这些数据存储到一个巨大的表中……
****************更新*****************
下面是完整的代码逻辑*******************
我刚刚删除了大部分与我的问题无关的属性和方法……</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;
}