具有 OneToMany 关系的 Symfony 5.3 空集合

Symfony 5.3 empty collection with a OneToMany relation

我的 Symfony 5 项目有 2 个实体:客户端和模板。 每个Client有一个或多个模板(OneToMany),每个模板只关联一个Client(ManyToOne)。 我在 Client.php 中有一个 getTemplates() 函数,其中 returns 模板集合。

我遇到的问题是,当我调用 getTemplates() 函数时,我 运行 它来自 :

$client = $entityManager->getRepository(Client::class)->find($id);
$templates = $client->getTemplates();

我正在获取一个 initialized = false 集合。

据我了解,为了避免不必要的请求,Symfony 创建了一个 Template 代理对象,它是 null。 为了完成这项工作,我可以添加 fetch="EAGER"

@ORM\OneToMany(targetEntity=Template::class, mappedBy="Client", orphanRemoval=true, fetch="EAGER")

添加这个基本上使请求成为“真正的”模板对象(更多信息here)。

我想做的是让我的 getTemplates 正常工作 当我像这里一样检索我的所有客户时不必请求所有模板(有时我只需要显示所有clients,然后向某个client请求模板):

$templateRepository->findAll()

我知道如何解决我的问题,我只是想用最好的方法来解决最少的请求到我的数据库(基本上只在我需要的时候调用它)。

综上所述,我想:

正如 Yassinefikri 所解释的,默认的 Symfony 行为是不请求链接的实体以避免性能不佳。

要解决这个问题,您需要在存储库中有一个适当的函数,您可以在其中获取客户端并将它们与它们的模板结合起来。

这允许获取所有没有他们的模板的客户,但也能够获取所有他们的模板的客户,关于是否需要。

通过添加 fetch="EAGER" 来改变 Symfony 的默认行为不是一个好习惯,你应该总是为想要的结果创建一个函数而不是改变默认行为(这会降低性能,特别是如果你正在处理有一个大数据库)。

- 编辑,解决问题的更好(和更优化)方法

正如 Will B 所说,行为来自 Doctrine ORM 而不是 Symfony (Symfony 经常与 Doctrine ORM 一起使用,但这通常适用于 ORM)

实现预期结果的另一种(更好的)方法是 initilialize 对象(这将获取链接的实体而不实际进行 JOIN 对数据库的请求 - initializeObject()).

总结

永远不要使用 fetch="EAGER" 如果可以的话,因为这确实是处理链接实体的工作方式,最好使用 Will B's or Yassinefikri's 解决问题。