2

我有一个用户实体。在这种情况下,这被认为是主要实体,并且它被使用的事实意味着它存在。

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

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

用户:

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 来解决(我无法找到一种方法来检查 Entity 对象是否存在或只是一个代理)。如果用户确实有商店记录,那么这里一切都很好。

但我遇到的最大问题尤其是夹具:

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

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

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

4

2 回答 2

1

在此文档页面上找到了解决方案:

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

在我的例子中,不是使用 id 字段将 User 实体与 Store 实体关联,而是通过用户(实体对象)将 User 实体中的 store 属性关联到 Store 实体。作为回报,Store 对象将保存一个 User 实体,该实体被注释为实体的 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;

    ...
}

现在,如果给定用户没有存储记录,则用户实体中的存储属性将为空。夹具也按预期运行。

于 2012-10-29T01:57:18.030 回答
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;

...
}
于 2016-04-26T22:08:21.523 回答