0

I'm using Doctrine in a project where I need data from multiple tables. In order to escape from N + 1 problem I'm fetching all the data, that I need before it go to the view. As I saw in the documentation the way to do this is to make a join with tables and then to call addSelect with the aliases of the joined table. The problem is that when I build the query that I need and call getResult, Doctrine returns me Collection of both entity objects and Proxies of the joined entity, which causes problems during the iteration of the array in the view, because Proxies don't have the same properties as the entity objects. I'm really confused of this behaviour. Can you help me in order to solve this issue?

zhelyazko777
  • 17
  • 1
  • 5
  • Please share more details such that others can understand the problem. For example, why do you use proxies that do not have the same properties? The proxies I have seen simply extend the original entity – Nico Haase Aug 11 '20 at 14:12
  • Yeah, but the proxes have the type of the joined entity. For example in the array I have objects from type A and Proxies from type B, where B is the joined entity – zhelyazko777 Aug 11 '20 at 14:14

1 Answers1

0

You get proxy objects because they are lazy loaded which is correct. You shouldn't have got any problems with them, because when you iterate over collection all data should be set correctly. Proxies generally behave like fully loaded entity. If you have got problems, maybe problem is somewhere else. However you can set fetch to EAGER in your relations to force build full entity.

@ManyToOne(targetEntity="target", fetch="EAGER")
@JoinColumn(name="target", referencedColumnName="id")

What's more you can use $query->getResult(Doctrine\ORM\Query::HYDRATE_ARRAY); to hydrate all objects in query. You can try as well $queryBuilder->getQuery()->setHint (Query::HINT_FORCE_PARTIAL_LOAD, true)->get();

You can also load proxy object by yourself during iteration. Something like that

foreach($collection as $object) {
    if ($object instanceof Doctrine\ORM\Proxy\Proxy) {
        $object->__load();
    }
}

However you may post your code (entities, query from repository and the view part) because there shouldn't be any problems with proxies.

Community
  • 1
  • 1
sabat
  • 136
  • 1
  • 11
  • I fixed the problem by changing the join from ```leftJoin(SomeClass::class, 't', Join::WITH, "o.id = t.someProperty")``` to ```leftJoin('o.someProperty', 't')```. Can you tell me what is the difference between the two statements? – zhelyazko777 Aug 12 '20 at 09:41
  • Second join uses a relation defined in your `o` / `t` entities. You defined there probably two properties with annotations like `@ManyToOne` and `@OneToMany`. This is why doctrine knows how to make a join. Because of that your child `SomeClass` objects are hydrated into parent object. They are auto hydrated because it is a fetch-join ( https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#joins ). When you work with relations the second join is the proper one. First one may be used if you want to make a join to something without relation. – sabat Aug 12 '20 at 10:08