Home > Mobile >  Symfony 5.3 empty collection with a OneToMany relation
Symfony 5.3 empty collection with a OneToMany relation

Time:10-28

I have on my Symfony 5 project, 2 entities : Client and Template. Each Client has one or more templates (OneToMany), each templates relates to only one Client (ManyToOne). I have a getTemplates() function in Client.php which returns a Collection of templates.

The problem I am getting is that when I call the getTemplates() function I run it from :

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

I am getting an initialized = false Collection.

From what I understand, to avoid unnecessary requests, Symfony creates a Template proxy object which is null. To make this work, I can add fetch="EAGER"

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

Adding this basically makes request the "real" Template object (more information here).

What I would like to do is make my getTemplates work without having to request all the templates when I retrieve all my clients like here (sometimes I only need to display all the clients, and request the templates from a certain client afterwards):

$templateRepository->findAll()

I know how to solve my problem, I just would like to have the best way to do it while having the smallest amount of requests to my database (basically only calling it when I need it).

To sum up, I would like to :

  • findAll() of my clients without retrieving the templates associated to the clients
  • findAll() of my templates and get the relating client - this currently works when I add a fetch="EAGER" since I get an "owner" which corresponds to the correct client

CodePudding user response:

As Yassinefikri explained, the default Symfony behavior is not to request the linked Entities to avoid bad performance.

To solve the problem, you need a proper function in the repository where you will fetch the Clients and join them with their Templates.

This allows to fetch all the Clients without their Template but also be able to fetch all the Clients with their Templates, regarding of if you need it or not.

Changing the default behavior of Symfony by adding a fetch="EAGER" is not good practice, you should always create a function for a desired result instead of changing default behavior (which would decrease performance, specially if you are dealing with a big DB).

- EDIT, Better (and more optimized) way of solving the problem

As Will B said, the behavior comes from Doctrine ORM and not not Symfony (Symfony frequently is used with Doctrine ORM but this applies to ORM in general).

Another (and better) way of achieving the desired result is to initilialize the object (which will fetch linked entities without actually making JOIN requests to the DB - initializeObject()).

TO SUM UP

NEVER use fetch="EAGER" if you can since this is really the work way of dealing with linked entities, it is ay better to use Will B's or Yassinefikri's solution to the problem.

  • Related