Doctrine2,传递Id还是Object?

时间:2012-07-10 14:46:17

标签: php orm doctrine-orm

我没有解释为什么对于某些Entity对象我可以设置Id而对于其他对象我得到一个错误并且告诉我Id不能为null而我必须传递一个对象。

e.g:

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

如果我尝试上面的代码,我会收到错误消息:完整性约束违规:1048列'user_id'不能为空。我必须首先创建Type Object和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());
    }

}
?>

2 个答案:

答案 0 :(得分:25)

现有的答案从未与我相提并论。有许多有效的场景,加载对象只是为了定义关系,而已经拥有FK的方便根本没有任何意义。

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

  

Reference Proxies...

     

方法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);

首次发布此问题时,可能无法使用此功能 - 我不知道。

答案 1 :(得分:3)

修改

我在Doctrine2的网站上发现了这个声明。这是编码模型时可能需要遵循的最佳实践。

Doctrine2 Best Practices

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

外键在对象模型中没有任何意义。外键是关系数据库建立关系的方式。您的对象模型通过对象引用建立关系。因此,将外键映射到对象字段会严重地将关系模型的细节泄漏到对象模型中,这是您真正不应该做的事情

修改

Doctrine执行从对象到各自ID的映射。

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

你基本上已经两次告诉学说。

你已经告诉它它有一个'user_id'列并且它也有一个User对象,这是同一个东西。但是,doctrine已经可以猜测这个关系会有一个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。学说将处理这个问题。

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

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