Doctrine2,通过Id或Object?

问题描述:

我不小心为什么有些实体对象可以设置ID和其他对象我得到一个错误,并说我的ID不能为空,我必须传递一个对象。Doctrine2,通过Id或Object?

例如为:

$log = new Log(); 
$log->setTypeId(1); 
$log->setUserId(1); 
$entityManager->persist($log); 
$entityManager->flush(); 

如果我尝试上面的代码,我得到的错误,说:完整性约束违规:1048列“user_ID的”不能为空。我必须先创建类型对象和DE用户对象和通过他们:

$log->setType($TypeObject) 
$log->setUser($UserObject) 

但是对于其他的实体对象我没有问题,直接分配值,这是为什么?

这是我的实体日志:

<?php 
/** 
* @Entity 
* @Table(name="log") 
* @HasLifecycleCallbacks 
*/ 
class Log 
{ 
    /** 
    * @var type 
    * @Id 
    * @Column(type="integer") 
    * @GeneratedValue 
    */ 
    protected $id; 

    /** 
    * 
    * @var type 
    * @Column(type="integer") 
    */ 
    protected $user_id; 

    /** 
    * 
    * @var type 
    * @Column(type="integer") 
    */ 
    protected $type_id; 

    /** 
    * 
    * @var type 
    * @Column(type="datetime") 
    */ 
    protected $created; 

    /** 
    * 
    * @var type 
    * @ManyToOne(targetEntity="User", inversedBy="logs") 
    */ 
    protected $user; 

    /** 
    * 
    * @ManyToOne(targetEntity="Type", inversedBy="logs") 
    */ 
    protected $type; 

    public function getId() 
    { 
     return $this->id; 
    } 

    public function getUserId() 
    { 
     return $this->user_id; 
    } 

    public function getTypeId() 
    { 
     return $this->type_id; 
    } 

    public function getCreated() 
    { 
     return $this->created; 
    } 

    public function setUserId($userId) 
    { 
     $this->user_id = $userId; 
    } 

    public function setTypeId($typeId) 
    { 
     $this->type_id = $typeId; 
    } 

    public function setCreated($created) 
    { 
     $this->created = $created; 
    } 

    public function setUser($user) 
    { 
     $this->user = $user; 
    } 

    public function setType($type) 
    { 
     $this->type = $type; 
    } 

    /** 
    * @PrePersist 
    */ 
    public function prePersist() 
    { 
     $this->setCreated(new DateTime()); 
    } 

} 
?> 
+1

很高兴帮助。这让我进入了1K大关。哇噢。 – 2012-08-01 19:36:53

编辑

我发现这个说法Doctrine2的网站上。编写模型时,您可能需要遵循这一最佳做法。

Doctrine2 Best Practices

25.9。不要将外键映射到实体中的字段

外键在对象模型中没有任何意义。外键是关系数据库如何建立关系。您的对象模型通过对象引用建立关系。因此映射外键对象字段严重泄漏了关系模型的细节到对象模型,有些东西你真的不应该做

编辑

主义确实从你的对象各自的ID的映射。

你在这里所做的有点多余。

你从本质上讲过两次同样的事情。

你已经告诉它它有一个'user_id'列,并且它也有一个User对象,它们是一样的。但是教条已经可以猜测,这种关系会有一个user_id列,这个列基于日志类里面有用户对象的事实。

你应该简单地做以下代替

<?php 
/** 
* @Entity 
* @Table(name="log") 
* @HasLifecycleCallbacks 
*/ 
class Log 
{ 
    /** 
    * @var type 
    * @Id 
    * @Column(type="integer") 
    * @GeneratedValue 
    */ 
    protected $id; 

    /** 
    * 
    * @var type 
    * @Column(type="datetime") 
    */ 
    protected $created; 

    /** 
    * 
    * @var type 
    * @ManyToOne(targetEntity="User", inversedBy="logs") 
    */ 
    protected $user; 

    /** 
    * 
    * @ManyToOne(targetEntity="Type", inversedBy="logs") 
    */ 
    protected $type; 

    public function getId() 
    { 
     return $this->id; 
    } 

    public function getCreated() 
    { 
     return $this->created; 
    } 

    public function setCreated($created) 
    { 
     $this->created = $created; 
    } 

    public function setUser($user) 
    { 
     $this->user = $user; 
    } 

    public function setType($type) 
    { 
     $this->type = $type; 
    } 

    /** 
    * @PrePersist 
    */ 
    public function prePersist() 
    { 
     $this->setCreated(new DateTime()); 
    } 

} 

主义会担心USER_ID和TYPE_ID在它自己的。你不必担心它。这样你就可以使用完整的对象,使编程更容易,而不必担心编号。主义会处理这个问题。

如果你拥有的是一个ID,因为这就是你在前端使用的,那么只需使用Entitymanager获取与该ID相关联的对象即可。

$user = $em->getEntity('User', $idFromWeb); 
$log = new Log(); 
$log->setUser($user); 
+1

从db中检索$ user似乎是一个开销。如果日志条目只需要UserId,为什么要检索整个用户记录。有什么办法可以避免这种情况? – 2012-10-11 06:11:16

+0

Mubix,你是对的。但是在这个请求中,您可能已经提取了用户实体以获取他们的偏好或验证密码信息或其他东西。 Doctrine2也只提取一次实体。如果多次调用getEntity,则Doctrine2将不返回数据库而继续返回相同的对象。 – 2012-10-11 22:17:39

+1

而在你正在做一些批处理操作并加载所有引用实体的场景中,只是为了让Doctrine拦截FK?有没有办法解决这个问题?我感到肮脏,所有这些额外的电话。要编写一个原始的PDO语句,或者不使用映射,只需通过控制器代码的存储库加载该实体。 – ficuscr 2014-01-31 05:48:10

现有的答案从来没有和我一起坐好。有许多有效的场景,加载一个对象只是为了定义关系,而已经拥有FK方便,根本没有任何意义。

更好的解决方案是使用Doctrine的EntityManager的getRefrence方法。

Reference Proxies...

的方法的EntityManager#getReference($的entityName,$标识符)让你 获得无负载该实体从数据库中的量,标识符是已知的实体, 的参考。这对于 示例很有用,因为您希望与您拥有标识符的实体建立关联 作为性能增强。你可以简单地 做到这一点:

<?php 
    // $em instanceof EntityManager, $cart instanceof MyProject\Model\Cart 
    // $itemId comes from somewhere, probably a request parameter 
    $item = $em->getReference(\MyProject\Model\Item::class, $itemId); 
    $cart->addItem($item); 

也许这时候没有这个问题首先发布 - 我不知道。

+3

我不知道这种方法,它看起来像原来的海报所要求的。 – 2014-02-04 15:39:52

+0

这是完美的。这是一项新功能吗? – pagliuca 2014-02-15 02:55:29

+0

我试图确定并且不确定何时变得可用(2.0>?)。在去年被添加。 – ficuscr 2014-02-20 01:47:09