Doctrine2,传递Id还是Object?

Pac*_*nSV 6 php orm doctrine-orm

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

例如:

$log = new Log();
$log->setTypeId(1);
$log->setUserId(1);
$entityManager->persist($log);
$entityManager->flush();
Run Code Online (Sandbox Code Playgroud)

如果我尝试上面的代码,我会收到错误消息:完整性约束违规:1048列'user_id'不能为空.我必须先创建Type Object和de User对象并传递它们:

$log->setType($TypeObject)
$log->setUser($UserObject)
Run Code Online (Sandbox Code Playgroud)

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

这是我的实体日志:

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

}
?>
Run Code Online (Sandbox Code Playgroud)

fic*_*scr 25

现有的答案从未与我相提并论.有许多有效的场景,加载一个对象只是为了定义关系,而已经拥有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);
Run Code Online (Sandbox Code Playgroud)

当这个问题首次发布时,这可能不可用 - 我不知道.

  • 我不知道这种方法,它看起来就像原始海报所要求的那样. (3认同)

Jer*_*via 3

编辑

\n\n

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

\n\n

Doctrine2 最佳实践

\n\n

25.9。Don\xe2\x80\x99t 将外键映射到实体中的字段

\n\n

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

\n\n

编辑

\n\n

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

\n\n

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

\n\n

你本质上已经对教义说了两次同样的事情。

\n\n

您已经告诉它它有一个“user_id”列并且它还有一个 User 对象,它们是同一件事。但是,根据日志类内部有一个 user 对象这一事实,学说已经可以猜测这种关系将有一个 user_id 列。

\n\n

你应该简单地执行以下操作

\n\n
<?php\n/**\n * @Entity\n * @Table(name="log")\n * @HasLifecycleCallbacks\n */\nclass Log\n{\n    /**\n     * @var type \n     * @Id\n     * @Column(type="integer")\n     * @GeneratedValue\n     */\n    protected $id;\n\n     /**\n     *\n     * @var type \n     * @Column(type="datetime")\n     */\n    protected $created;\n\n    /**\n     *\n     * @var type \n     * @ManyToOne(targetEntity="User", inversedBy="logs")\n     */\n    protected $user;\n\n    /**\n     *\n     * @ManyToOne(targetEntity="Type", inversedBy="logs")\n     */\n    protected $type;\n\n    public function getId()\n    {\n        return $this->id;\n    }\n\n    public function getCreated()\n    {\n        return $this->created;\n    }\n\n    public function setCreated($created)\n    {\n        $this->created = $created;\n    }\n\n    public function setUser($user)\n    {\n        $this->user = $user;\n    }\n\n    public function setType($type)\n    {\n        $this->type = $type;\n    }\n\n    /**\n     * @PrePersist\n     */\n    public function prePersist()\n    {\n        $this->setCreated(new DateTime());\n    }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

Doctrine 会自己担心 user_id 和 type_id 。您不必担心。通过这种方式,您可以使用成熟的对象,从而更容易编程,而不必担心 id。教义会处理这个问题。

\n\n

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

\n\n
$user = $em->getEntity( \'User\', $idFromWeb );\n$log = new Log();\n$log->setUser( $user );\n
Run Code Online (Sandbox Code Playgroud)\n

  • 在这样的场景中,您正在执行一些批处理操作并加载所有引用的实体,只是为了让 Doctrine 抓住 FK?难道就没有办法解决这个问题吗?我觉得打这些额外的电话很肮脏。要编写原始 PDO 语句,或者不使用映射,而只是从控制器代码通过存储库加载该实体。 (3认同)