Doctrine是实体中的可删除方法


Doctrine isDeletable method in entity

我在我的数据库中有一个实体(说成员),它与其他表有许多关系(确切地说是6个关系)。其中一些我不想映射到ORM(我的意思是链接到这个实体),因为它们可能有许多记录(如MemberAccessLogs)和其他一些加载许多其他实体。

现在我希望这个成员实体有一个isdelete方法,这样我就可以在管理页面中禁用排除按钮。

如果我要用传统的方式做这件事,我将不得不声明与实体类中所有其他表的关联,包括MemberAccessLogs,并且我将在其中放置方法,以便我可以测试这些关联是否为空。

但是,为了检查是否为空,我必须对关联的表进行一次读取(或至少一次计数)。

另一种方法是获取我想要显示的成员,然后在这些子表中使用低成本存在(select * from table limit 1)检查空的单独查询,然后以编程方式填充Member中的isdelettable方法,然后将其传递给Twig。

但是我发现这个解决方案很麻烦。有人有更好的方法吗?

只是为了记录:有些人可能会认为这是"过早优化"。我坚持(与某些人相反),你应该在编程时提前考虑,不要这样做,这是不好的。但我真的觉得这不是讨论的地方。让我们专注于刚才的问题,好吗?:)

编辑

为了简单地证明limit 1比count快得多,我在数据库中一个超过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

你可以看看extra-lazy关联

基本上你像往常一样映射所有关联,并添加fetch="EXTRA_LAZY":

/**
 * @Entity
 */
class CmsGroup
{
    /**
     * @ManyToMany(targetEntity="CmsUser", mappedBy="groups", fetch="EXTRA_LAZY")
     */
    public $users;
}

现在Doctrine不会在第一次访问时将完整的集合加载到内存中,而是执行专门的查询来加载当时实际需要的部分

所以集合上的$users->count()(或count($users))将触发一个简单的计数查询,而不是将整个集合加载到内存中。

PostLoad

您可以使用postLoad事件来确定这样的实体是否可删除。这个postLoad事件在实体被EntityManager构造之后被调用,所以当实体被加载时。

为实体添加一个未映射属性($isDeletable),用于存储实体是否可以删除。

创建一个侦听postLoad事件的实体侦听器。侦听器可以注入EntityManager、DBAL Connection或其他任何东西。有了这个依赖项,你可以执行任何你想要的查询,并使用结果来设置$isDeletable

当实体被加载时,结果是一个额外的查询,之后实体"知道"它是否可以删除。

使用postLoad事件的示例可以在策略模式

的Cookbook条目中找到

请注意,当决定是否可删除的条件发生变化时,$isDeletable的值可能会变得不正确。要解决这个问题,您可以跟踪这些条件:

跟踪

为实体添加一个映射的属性($isDeletable),用于存储实体是否可以删除。它可能从true开始。

当向关联中添加某些内容时,将意味着该实体不再可删除,将$isDeletable设置为false

当从关联中删除某些内容时,意味着该实体将再次被删除,设置$isDeletabletrue

换句话说:在每次更改时,您都要跟踪实体是否可删除。

这样你就不需要任何额外的查询了。

有一个关于聚合字段的Cookbook条目很好地解释了这个概念。