具有 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()
我知道如何解决我的问题,我只是想用最好的方法来解决最少的请求到我的数据库(基本上只在我需要的时候调用它)。
综上所述,我想:
- 我的客户的
- findAll() 没有检索与客户关联的模板
- findAll() 我的模板并获取相关的客户端 - 这在我添加 fetch="EAGER" 时有效,因为我得到了一个“所有者” " 对应于正确的客户端
正如 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 解决问题。
我的 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()
我知道如何解决我的问题,我只是想用最好的方法来解决最少的请求到我的数据库(基本上只在我需要的时候调用它)。
综上所述,我想:
- 我的客户的
- findAll() 没有检索与客户关联的模板
- findAll() 我的模板并获取相关的客户端 - 这在我添加 fetch="EAGER" 时有效,因为我得到了一个“所有者” " 对应于正确的客户端
正如 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 解决问题。