ZF2 项目中的 Doctrine 2 延迟加载问题
Doctrine 2 lazy loading issue in ZF2 project
好的,一言以蔽之:帮助!
有些事情我想不通。在 ZF2 中,我使用了很棒的 Doctrine Orm 模块。一切都很完美,但今天我发现了一些奇怪的事情。
我想我的某个地方一定有错误,但我找不到。又或者在 Doctrine 2 中有一些我没有理解清楚的地方。
我已经映射了我的实体。当我在没有指定获取选项的情况下建立多对一关系时,当我通过调用存储库上的 find() 方法获取一个实体时,我可以看到我的属性按预期包含代理 class 生成的实例.但是当我在该属性上调用 setter 时,它仍然包含代理的空实例 class ???
似乎 Doctrine 无法将实例链接到我的实体。在我的例子中,我从 find() 方法获得的实体是关系的所有者。
如果我在我的映射中指定了 EAGER 上的获取选项,那么调用 find() 方法 returns 一个实体,其属性按预期包含 class 中指定的实例关系。
有人遇到过同样的问题吗?
编辑:
好的,所以我创建了一个新的 ZF2 项目以确保没有任何干扰。
所以我有两个实体组和用户:
/**
* Class Group
* @package Application\Entity
* @Entity
* @Table("`group`")
*/
class Group
{
/**
* @Id
* @GeneratedValue
* @Column(type="integer", options={"unsigned"=true})
*/
private $id;
/**
* @Column(type="string")
*/
private $name;
/**
* @OneToMany(targetEntity="User", mappedBy="group")
*/
private $users;
}
/**
* Class User
* @package Application\Entity
* @Entity
* @Table(name="user")
*/
class User
{
/**
* @Id
* @GeneratedValue
* @Column(type="integer", options={"unsigned"=true})
*/
private $id;
/**
* @Column(type="string")
*/
private $firstName;
/**
* @Column(type="string")
*/
private $lastName;
/**
* @ManyToOne(targetEntity="Group", inversedBy="users")
* @JoinColumn(name="groupId", referencedColumnName="id")
*/
private $group;
}
当然,我在两个 class 中都有所有的 getter 和 setter,但我没有将它们放在示例中以加快速度。
在我的控制器中,我做了一件非常简单的事情来测试没有视图:
$user = $this->serviceLocator->get('doctrine.entitymanager.orm_default')->getRepository('Application\Entity\User')->find(1);
var_dump($user->getGroup());exit;
var_dump显示:
object(DoctrineORMModule\Proxy\__CG__\Application\Entity\Group)[367]
public '__initializer__' =>
object(Closure)[362]
public '__cloner__' =>
object(Closure)[363]
public '__isInitialized__' => boolean false
private 'id' (Application\Entity\Group) => int 1
private 'name' (Application\Entity\Group) => null
当然,我在数据库中添加了用户和组,我在 table 组的一组中有一个 ID 为 1 的用户。
也许我错过了一个选项之类的?为了配置 Doctrine 模块,我只是按照 github 上的文档进行操作,所以在这里我给出了注释驱动程序和我的实体的目录,当然还有数据库凭证。
这完全是预料之中的行为,因为学说是延迟加载您的组实体。这是因为您所做的只是:
$user->getGroup();
我将尝试解释为什么您只能在这里获得代理:
您已经从数据库解析的 User
实体拥有您的组实体的标识符(在本例中为 id = 1
)(此 ID 来自 groupId
列 user
table)。当你调用 getGroup
时,学说只会为你的 Group
实体创建一个代理,并将其 id
设置为 1
。到目前为止不需要数据库交互。
由于您没有向 Group
实体请求任何其他内容,因此在这种简单情况下代理就足够了。一旦您从您的组实体请求另一个 属性(任何其他直接 属性(您的组 table 中的列)但标识符),您会立即注意到差异。例如,尝试在您的群组实体上调用 getName()
。此 属性 尚未加载,因此学说将从数据库中的 group
table 中获取带有 id = 1
的行,并将所有列加载为属性(在本例中有只有一个)在您的组对象中,然后它将 return 所请求名称的值。
所以像这样尝试一次:
$user->getGroup()->getName();
而且你的输出会有很大的不同。
我希望这能让行为更容易理解。
好的,一言以蔽之:帮助!
有些事情我想不通。在 ZF2 中,我使用了很棒的 Doctrine Orm 模块。一切都很完美,但今天我发现了一些奇怪的事情。 我想我的某个地方一定有错误,但我找不到。又或者在 Doctrine 2 中有一些我没有理解清楚的地方。
我已经映射了我的实体。当我在没有指定获取选项的情况下建立多对一关系时,当我通过调用存储库上的 find() 方法获取一个实体时,我可以看到我的属性按预期包含代理 class 生成的实例.但是当我在该属性上调用 setter 时,它仍然包含代理的空实例 class ???
似乎 Doctrine 无法将实例链接到我的实体。在我的例子中,我从 find() 方法获得的实体是关系的所有者。
如果我在我的映射中指定了 EAGER 上的获取选项,那么调用 find() 方法 returns 一个实体,其属性按预期包含 class 中指定的实例关系。
有人遇到过同样的问题吗?
编辑: 好的,所以我创建了一个新的 ZF2 项目以确保没有任何干扰。 所以我有两个实体组和用户:
/**
* Class Group
* @package Application\Entity
* @Entity
* @Table("`group`")
*/
class Group
{
/**
* @Id
* @GeneratedValue
* @Column(type="integer", options={"unsigned"=true})
*/
private $id;
/**
* @Column(type="string")
*/
private $name;
/**
* @OneToMany(targetEntity="User", mappedBy="group")
*/
private $users;
}
/**
* Class User
* @package Application\Entity
* @Entity
* @Table(name="user")
*/
class User
{
/**
* @Id
* @GeneratedValue
* @Column(type="integer", options={"unsigned"=true})
*/
private $id;
/**
* @Column(type="string")
*/
private $firstName;
/**
* @Column(type="string")
*/
private $lastName;
/**
* @ManyToOne(targetEntity="Group", inversedBy="users")
* @JoinColumn(name="groupId", referencedColumnName="id")
*/
private $group;
}
当然,我在两个 class 中都有所有的 getter 和 setter,但我没有将它们放在示例中以加快速度。
在我的控制器中,我做了一件非常简单的事情来测试没有视图:
$user = $this->serviceLocator->get('doctrine.entitymanager.orm_default')->getRepository('Application\Entity\User')->find(1);
var_dump($user->getGroup());exit;
var_dump显示:
object(DoctrineORMModule\Proxy\__CG__\Application\Entity\Group)[367]
public '__initializer__' =>
object(Closure)[362]
public '__cloner__' =>
object(Closure)[363]
public '__isInitialized__' => boolean false
private 'id' (Application\Entity\Group) => int 1
private 'name' (Application\Entity\Group) => null
当然,我在数据库中添加了用户和组,我在 table 组的一组中有一个 ID 为 1 的用户。
也许我错过了一个选项之类的?为了配置 Doctrine 模块,我只是按照 github 上的文档进行操作,所以在这里我给出了注释驱动程序和我的实体的目录,当然还有数据库凭证。
这完全是预料之中的行为,因为学说是延迟加载您的组实体。这是因为您所做的只是:
$user->getGroup();
我将尝试解释为什么您只能在这里获得代理:
您已经从数据库解析的 User
实体拥有您的组实体的标识符(在本例中为 id = 1
)(此 ID 来自 groupId
列 user
table)。当你调用 getGroup
时,学说只会为你的 Group
实体创建一个代理,并将其 id
设置为 1
。到目前为止不需要数据库交互。
由于您没有向 Group
实体请求任何其他内容,因此在这种简单情况下代理就足够了。一旦您从您的组实体请求另一个 属性(任何其他直接 属性(您的组 table 中的列)但标识符),您会立即注意到差异。例如,尝试在您的群组实体上调用 getName()
。此 属性 尚未加载,因此学说将从数据库中的 group
table 中获取带有 id = 1
的行,并将所有列加载为属性(在本例中有只有一个)在您的组对象中,然后它将 return 所请求名称的值。
所以像这样尝试一次:
$user->getGroup()->getName();
而且你的输出会有很大的不同。
我希望这能让行为更容易理解。