实体中的 Doctrine isDeletable 方法
Doctrine isDeletable method in entity
我的数据库中有一个实体(比如成员),它与其他 table 有很多关系(准确地说是 6 个关系)。其中一些我不想用 ORM 映射(我的意思是链接到这个实体),因为它们可能有很多记录(例如 MemberAccessLogs),而其他一些加载许多其他实体。
现在我希望这个成员实体有一个 isDeletable 方法,这样我就可以在管理页面中禁用排除按钮。
如果我在哪里以传统方式执行此操作,我将不得不声明与实体 class 中所有其他 table 的关联,包括 MemberAccessLogs,我会将方法放在这样我就可以测试这些关联是否为空。
但是 AFAIU,我必须对协会的 table 进行提取(或至少计数)以检查是否为空。
另一种方法是获取我想要显示的成员,然后进行单独的查询以检查这些子中是否存在低成本的空成员(select * 来自 table 限制 1) -tables 然后在将它传递给 Twig 之前以编程方式在 Member 中填充 isDeletable 方法。
但我发现这个解决方案很麻烦。谁有更好的方法来做到这一点?
郑重声明:有些人可能认为这是 "premature optimization"。我坚持认为(与某些人相反),您在编程时应该提前考虑,这不是一件坏事。但我真的认为这不是讨论它的地方。请让我们专注于提出的问题好吗? :)
编辑
为了轻松证明 limit 1 比 count 快得多,我在我的数据库 table 中做了一个小测试,该数据库有超过 2000 万行。以下是结果:
select count(*) from loga [20 million+ table]
20678473
1 row(s) fetched - 27023ms
select exists(select null from loga limit 1)
true
1 row(s) fetched - 2ms
我猜13511,快5倍就够了。 :D
特别懒惰
你可以看看 extra-lazy associations.
基本上,您像往常一样映射所有关联,并添加 fetch="EXTRA_LAZY"
:
/**
* @Entity
*/
class CmsGroup
{
/**
* @ManyToMany(targetEntity="CmsUser", mappedBy="groups", fetch="EXTRA_LAZY")
*/
public $users;
}
现在 Doctrine 将 不会 将 complete 集合在第一次访问时加载到内存中,但会执行专门的查询来加载 零件你当时确实需要。
因此,集合上的 $users->count()
(或 count($users)
)将触发一个简单的计数查询,而不是将整个集合加载到内存中。
后加载
您可以使用 postLoad
事件来确定此类实体是否可删除。此 postLoad
事件在 EntityManager 构造实体后调用,因此在加载实体时调用。
给实体添加一个未映射的属性($isDeletable
),存储实体是否可以删除。
创建一个 entity listener 来侦听 postLoad
事件。侦听器可以注入 EntityManager、DBAL Connection 或任何其他内容。有了这种依赖,你可以执行任何你想要的查询,并使用结果来设置 $isDeletable
.
结果是加载实体时的单个附加查询,之后实体 "knows" 是否可删除。
可以在 Cookbook entry on the Strategy Pattern
中找到使用 postLoad
事件的示例
请注意,当确定是否可删除的条件发生变化时,$isDeletable
的值可能会变得不正确。要解决此问题,您可以跟踪这些情况:
保持跟踪
实体添加一个mapped 属性 ($isDeletable
),存储实体是否可以删除。它可能以 true
.
开头
当将某些内容添加到关联中意味着实体不再可删除时,将 $isDeletable
设置为 false
。
当从关联中删除某些内容时,这意味着该实体可再次删除,将 $isDeletable
设置为 true
。
换句话说:对于每次更改,您都会跟踪实体是否可删除。
这样您就根本不需要任何额外的查询。
有个Cookbook entry on aggregate fields很好地解释了这个概念。
我的数据库中有一个实体(比如成员),它与其他 table 有很多关系(准确地说是 6 个关系)。其中一些我不想用 ORM 映射(我的意思是链接到这个实体),因为它们可能有很多记录(例如 MemberAccessLogs),而其他一些加载许多其他实体。
现在我希望这个成员实体有一个 isDeletable 方法,这样我就可以在管理页面中禁用排除按钮。
如果我在哪里以传统方式执行此操作,我将不得不声明与实体 class 中所有其他 table 的关联,包括 MemberAccessLogs,我会将方法放在这样我就可以测试这些关联是否为空。
但是 AFAIU,我必须对协会的 table 进行提取(或至少计数)以检查是否为空。
另一种方法是获取我想要显示的成员,然后进行单独的查询以检查这些子中是否存在低成本的空成员(select * 来自 table 限制 1) -tables 然后在将它传递给 Twig 之前以编程方式在 Member 中填充 isDeletable 方法。
但我发现这个解决方案很麻烦。谁有更好的方法来做到这一点?
郑重声明:有些人可能认为这是 "premature optimization"。我坚持认为(与某些人相反),您在编程时应该提前考虑,这不是一件坏事。但我真的认为这不是讨论它的地方。请让我们专注于提出的问题好吗? :)
编辑
为了轻松证明 limit 1 比 count 快得多,我在我的数据库 table 中做了一个小测试,该数据库有超过 2000 万行。以下是结果:
select count(*) from loga [20 million+ table]
20678473
1 row(s) fetched - 27023ms
select exists(select null from loga limit 1)
true
1 row(s) fetched - 2ms
我猜13511,快5倍就够了。 :D
特别懒惰
你可以看看 extra-lazy associations.
基本上,您像往常一样映射所有关联,并添加 fetch="EXTRA_LAZY"
:
/**
* @Entity
*/
class CmsGroup
{
/**
* @ManyToMany(targetEntity="CmsUser", mappedBy="groups", fetch="EXTRA_LAZY")
*/
public $users;
}
现在 Doctrine 将 不会 将 complete 集合在第一次访问时加载到内存中,但会执行专门的查询来加载 零件你当时确实需要。
因此,集合上的 $users->count()
(或 count($users)
)将触发一个简单的计数查询,而不是将整个集合加载到内存中。
后加载
您可以使用 postLoad
事件来确定此类实体是否可删除。此 postLoad
事件在 EntityManager 构造实体后调用,因此在加载实体时调用。
给实体添加一个未映射的属性($isDeletable
),存储实体是否可以删除。
创建一个 entity listener 来侦听 postLoad
事件。侦听器可以注入 EntityManager、DBAL Connection 或任何其他内容。有了这种依赖,你可以执行任何你想要的查询,并使用结果来设置 $isDeletable
.
结果是加载实体时的单个附加查询,之后实体 "knows" 是否可删除。
可以在 Cookbook entry on the Strategy Pattern
中找到使用postLoad
事件的示例
请注意,当确定是否可删除的条件发生变化时,$isDeletable
的值可能会变得不正确。要解决此问题,您可以跟踪这些情况:
保持跟踪
实体添加一个mapped 属性 ($isDeletable
),存储实体是否可以删除。它可能以 true
.
当将某些内容添加到关联中意味着实体不再可删除时,将 $isDeletable
设置为 false
。
当从关联中删除某些内容时,这意味着该实体可再次删除,将 $isDeletable
设置为 true
。
换句话说:对于每次更改,您都会跟踪实体是否可删除。
这样您就根本不需要任何额外的查询。
有个Cookbook entry on aggregate fields很好地解释了这个概念。