Fetch joins and EntityManager::find() returns proxy #5223

Closed
opened 2026-01-22 15:01:57 +01:00 by admin · 6 comments
Owner

Originally created by @mreiche on GitHub (Aug 19, 2016).

Originally assigned to: @kimhemsoe on GitHub.

Hi. Im querying entites as a fetch join in DQL
SELECT d,s FROM domains d JOIN d.site s

d.site is defined as
@ManyToOne(targetEntity="Site", inversedBy="assignedDomains", fetch="LAZY")

But one of these entities is returned as a proxy when I log the output of the result.

$site = $domain->getSite();
Log::info('nav', get_class($site).': '.$site->getId());
if ($site instanceof Proxy) {
    $site2 = $em->find(Site::class,$site->getId());
    Log::info('nav', 'loaded: ' . get_class($site2).': '.$site2->getId());
}

log:

[nav] INFO: models\Site: 43
[nav] INFO: models\Site: 44 
[nav] INFO: models\Site: 45 
[nav] INFO: DoctrineProxies\__CG__\models\Site: 46 
[nav] INFO: loaded: DoctrineProxies\__CG__\models\Site: 46
[nav] INFO: models\Site: 47 
[nav] INFO: models\Site: 48 
[nav] INFO: models\Site: 49 
[nav] INFO: models\Site: 50

As you can see, that even when I try to load the entity with EntityManager::find() I still get a proxy object of this entity.

Im using Doctrine 2.5.4

Originally created by @mreiche on GitHub (Aug 19, 2016). Originally assigned to: @kimhemsoe on GitHub. Hi. Im querying entites as a fetch join in DQL `SELECT d,s FROM domains d JOIN d.site s` d.site is defined as `@ManyToOne(targetEntity="Site", inversedBy="assignedDomains", fetch="LAZY")` But one of these entities is returned as a proxy when I log the output of the result. ``` $site = $domain->getSite(); Log::info('nav', get_class($site).': '.$site->getId()); if ($site instanceof Proxy) { $site2 = $em->find(Site::class,$site->getId()); Log::info('nav', 'loaded: ' . get_class($site2).': '.$site2->getId()); } ``` log: ``` [nav] INFO: models\Site: 43 [nav] INFO: models\Site: 44 [nav] INFO: models\Site: 45 [nav] INFO: DoctrineProxies\__CG__\models\Site: 46 [nav] INFO: loaded: DoctrineProxies\__CG__\models\Site: 46 [nav] INFO: models\Site: 47 [nav] INFO: models\Site: 48 [nav] INFO: models\Site: 49 [nav] INFO: models\Site: 50 ``` As you can see, that even when I try to load the entity with EntityManager::find() I still get a proxy object of this entity. Im using Doctrine 2.5.4
admin added the BugInvalid labels 2026-01-22 15:01:57 +01:00
admin closed this issue 2026-01-22 15:01:57 +01:00
Author
Owner

@kimhemsoe commented on GitHub (Aug 19, 2016):

I am guessing that the Site entity with id 46 has its proxy created by relation from another previous loaded entity.

Try to look after entities with relations to Site which could have been loaded.

@kimhemsoe commented on GitHub (Aug 19, 2016): I am guessing that the Site entity with id 46 has its proxy created by relation from another previous loaded entity. Try to look after entities with relations to Site which could have been loaded.
Author
Owner

@mreiche commented on GitHub (Aug 19, 2016):

@kimhemsoe The Site entity 46 is definitively already loaded, it is the current site im working on.

@mreiche commented on GitHub (Aug 19, 2016): @kimhemsoe The Site entity 46 is definitively already loaded, it is the current site im working on.
Author
Owner

@kimhemsoe commented on GitHub (Aug 19, 2016):

Then you have your answer why it is a proxy.

When you load $domain it will create proxy for site 46. That is how doctrine works. If you want to avoid that. You will need to fetch site 46 when loading the domain. You can this with dql.

@kimhemsoe commented on GitHub (Aug 19, 2016): Then you have your answer why it is a proxy. When you load $domain it will create proxy for site 46. That is how doctrine works. If you want to avoid that. You will need to fetch site 46 when loading the domain. You can this with dql.
Author
Owner

@mreiche commented on GitHub (Aug 19, 2016):

It seems that I misunterstand the concept of fetch joins.
In reference to the documentation: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#joins

Doctrine allows you to walk all the associations between all the objects in your domain model. Objects that were not already loaded from the database are replaced with lazy load proxy instances. Non-loaded Collections are also replaced by lazy-load instances that fetch all the contained objects upon first access. However relying on the lazy-load mechanism leads to many small queries executed against the database, which can significantly affect the performance of your application. Fetch Joins are the solution to hydrate most or all of the entities that you need in a single SELECT query.

A fetch join is exactly what Im doing with DQL:

public function loadAllDomainsAndSites() {
    $query = $this->getEntityManager()->createQuery('SELECT d,s FROM '.$this->getClassName().' JOIN d.site s');
    return $query->execute();
}

I expect no Proxies in this result. What I'm doing wrong here? Is there a difference between $query->execute() and $query->getResult() in this case?

@mreiche commented on GitHub (Aug 19, 2016): It seems that I misunterstand the concept of fetch joins. In reference to the documentation: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#joins > Doctrine allows you to walk all the associations between all the objects in your domain model. Objects that were not already loaded from the database are replaced with lazy load proxy instances. Non-loaded Collections are also replaced by lazy-load instances that fetch all the contained objects upon first access. However relying on the lazy-load mechanism leads to many small queries executed against the database, which can significantly affect the performance of your application. Fetch Joins are the solution to hydrate most or all of the entities that you need in a single SELECT query. A fetch join is exactly what Im doing with DQL: ``` public function loadAllDomainsAndSites() { $query = $this->getEntityManager()->createQuery('SELECT d,s FROM '.$this->getClassName().' JOIN d.site s'); return $query->execute(); } ``` I expect no Proxies in this result. What I'm doing wrong here? Is there a difference between `$query->execute()` and `$query->getResult()` in this case?
Author
Owner

@kimhemsoe commented on GitHub (Aug 19, 2016):

That is the correct way to do a fetch join.

If you still see the proxy, it is because that that entity already had been created. It is not possible to "replace" an object reference and there can only be one instance of each entity. So even if you load the data for site 46, it does not magical convert it to an none proxy.

There is nothing wrong proxies and you should not try to work against them. They are there to make your job easier. So i would look pass them and figure different ways to archive your goals.

ex.
Log::info('nav', 'loaded: ' . $site->getClassName() .': '.$site2->getId());
Or something like that.

execute() executes and getResult() returns result and executes if needed. There is difference in using either.

@kimhemsoe commented on GitHub (Aug 19, 2016): That is the correct way to do a fetch join. If you still see the proxy, it is because that that entity already had been created. It is not possible to "replace" an object reference and there can only be one instance of each entity. So even if you load the data for site 46, it does not magical convert it to an none proxy. There is nothing wrong proxies and you should not try to work against them. They are there to make your job easier. So i would look pass them and figure different ways to archive your goals. ex. Log::info('nav', 'loaded: ' . $site->getClassName() .': '.$site2->getId()); Or something like that. execute() executes and getResult() returns result and executes if needed. There is difference in using either.
Author
Owner

@mreiche commented on GitHub (Aug 19, 2016):

Got that. Ok I'm looking for a workaround by myself. Thanks.

@mreiche commented on GitHub (Aug 19, 2016): Got that. Ok I'm looking for a workaround by myself. Thanks.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#5223