2012-10-28 49 views
2

我有一个用户实体。这被认为是这种情况下的主要实体,它被使用的事实意味着它存在。实体之间的可选OneToOne关系?

用户实体拥有一个Store实体。但并非所有用户都必须拥有Store实体。

值得注意的是,这是我们正在使用的现有数据库,并且User表的id与Store表的id相同。名称(id)和值。只是在某些情况下,Store没有给定用户标识的记录。

用户:

class User extends Entity 
{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="string", length=36) 
    */ 
    protected $id; 

    /** 
    * @ORM\OneToOne(targetEntity="Store") 
    * @ORM\JoinColumn(name="id", referencedColumnName="id") 
    */ 
    protected $store; 

    ... 
} 

商店:

class Store extends Entity 
{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="string", length=36) 
    */ 
    protected $id; 

    ... 
} 

这会导致控制器的问题。如果用户实体没有存储记录,则会失败并显示“未找到实体”异常。这可以使用一个try catch来处理,这很容易(我还没有找到一种方法来检查一个实体对象是否存在或者只是一个代理)。如果用户确实有商店记录,这里一切都很好。

但最大的问题,我有特别的灯具:

protected function createUser($id) 
{ 
    $user = new User(); 
    $user->setId($id); 
    $user->setEmail($id.'@example.com'); 
    $user->setUserName($id.'_name'); 
    $user->setArea($this->manager->find('Area', 156)); // Global 

    $this->manager->persist($user); 

    return $user; 
} 

当我运行灯具,失败。给我错误“完整性约束违规:1048列'id'不能为空”。如果我从用户中删除商店实体,此消息将消失。所以简而言之,如果用户没有商店,我无法添加用户。

任何人都知道发生了什么?我已经做了一些四处寻找,我找不到任何东西,包括教义文档,有实体之间的可选关系。我认为这是一种常见的情况。

回答

1

发现这个文档页面上的解决方案,这一点:

http://docs.doctrine-project.org/en/latest/tutorials/composite-primary-keys.html#use-case-3-join-table-with-metadata

在我的情况,而不是用户实体正在使用的ID字段,在用户实体店物业的商店实体相关联将被用户(一个实体对象)关联到Store实体。作为回报,Store对象将持有一个用户实体,该实体被注释为实体的ID。

我敢肯定这就像地狱一样令人困惑,所以看看上面的示例吧。下面是我的调整实体类:

用户

class User extends Entity 
{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="string", length=36) 
    */ 
    protected $id; 

    /** 
    * @ORM\OneToOne(targetEntity="Store", mappedBy="user") 
    */ 
    protected $store; 

    ... 
} 

商店

class Store extends Entity 
{ 
    /** 
    * @ORM\Column(type="string", length=36) 
    */ 
    protected $id; 

    /** 
    * @ORM\Id 
    * @ORM\OneToOne(targetEntity="User") 
    * @ORM\JoinColumn(name="id", referencedColumnName="id") 
    */ 
    protected $user; 

    ... 
} 

现在,如果不存在一个给定用户存储记录,在用户实体店物业会空值。赛程也按预期运行。

0

除了上面的答案,我还需要添加一个inversedBy属性。否则,将抛出无效的实体映射错误。

使用上述实体的Store对象需要是这样的:

class Store extends Entity 
{ 
/** 
* @ORM\Column(type="string", length=36) 
*/ 
protected $id; 

/** 
* @ORM\Id 
* @ORM\OneToOne(targetEntity="User", inversedBy="store") 
* @ORM\JoinColumn(name="id", referencedColumnName="id") 
*/ 
protected $user; 

... 
}