Doctrine2, pass Id or Object?


Doctrine2, pass Id or Object?

我不明白为什么对于一些Entity对象,我可以设置Id,而对于其他对象,我收到了一个错误,并告诉我Id不能为null,我必须传递一个对象。

例如:

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

如果我尝试上面的代码,我会得到一个错误:违反完整性约束:1048列"user_id"不能为null。我必须首先创建Type对象和de User对象,然后传递它们:

$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());
    }
}
?>

我对现有的答案从来都不满意。在许多有效的场景中,加载对象只是为了定义关系,而已经有了FK,这根本没有任何意义。

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

引用代理

EntityManager#getReference($entityName,$identifier)方法让您获得了对标识符已知的实体的引用,而不从数据库加载该实体。这很有用,因为例如,作为性能增强,当您想要建立关联到具有标识符的实体。你可以只需这样做:

<?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);

也许这个问题第一次发布时还没有——我不知道。

编辑

我在Doctrine2的网站上找到了这份声明。这是在对模型进行编码时可能需要遵循的最佳实践。

Doctrine2最佳实践

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());
    }
}

Doctrine会担心自己的user_id和type_id。你不必担心。这样你就可以使用成熟的对象,使编程更容易,而不必担心id。原则会处理这个问题。

如果您的ALL是一个id,因为这是您在前端使用的,那么只需使用Entitymanager获取与该id关联的对象。

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