How to get an object with all its associations using EntityManager in Doctrine2?

I have a simple object with many-to-many and one-to-many associations. I know "Unification" to get related associations, which is a manual solution to my problem.

How can I get an object with all its associations using EntityManager in Doctrine2? eg:.

$this->em ->getRepository('Entities\Patientprofile') ->findOneByuserid('555555557') ->fetchAllAssociations(); 
+6
source share
4 answers

Doctrine 2 uses proxy classes for lazy loading, so you don't actually need to get association data until you use objects. Because Proxy classes are inherited from your association classes, you can use proxies just like you would use fretch association classes.

but if you really need to get the actual association classes, you need to tell the query to set the fetch mode to Doctrine \ ORM \ Mapping \ ClassMetadata :: FETCH_EAGER. If you use annotations, you can achieve this with:

eg.

 /** * @ManyToMany(targetEntity="Item", fetch="EAGER") */ private $items; 
+9
source

from http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html#temporary-change-fetch-mode-in-dql

You can temporarily set the active boot mode:

 $query = $em->createQuery("SELECT u FROM MyProject\User u"); $query->setFetchMode("MyProject\User", "address", "EAGER"); $query->execute(); 

If you want to dynamically load all associations with this selection mode, you can use the getAssociationMappings() method from Doctrine\ORM\Mapping\ClassMetadataInfo , passing the name of your entity as a parameter to the ClassMetadataInfo constructor and then ClassMetadataInfo over the returned array as $ associate and call:

 $query->setFetchMode("MyProject\User", $assoc, "EAGER"); 

Document: ClassMetadataInfo # getAssociationMappings ()

+19
source

Doctrine2 setFetchMode not working with "EAGER"

I also tried to extract related entities โ€œwillinglyโ€ using setFetchMode in my request, but the following did not seem to work:

 $query->setFetchMode("MyProject\User", "address", "EAGER"); 

When I jumped into the files, I found that the third parameter of $fetchMode should be an integer . Constants are defined in Doctrine \ ORM \ Mapping: ClassMetadataInfo. When transferring a string, Mapping\ClassMetadata::FETCH_LAZY used by default due to this if condition .

 /** * Specifies that an association is to be fetched when it is first accessed. */ const FETCH_LAZY = 2; /** * Specifies that an association is to be fetched when the owner of the * association is fetched. */ const FETCH_EAGER = 3; /** * Specifies that an association is to be fetched lazy (on first access) and that * commands such as Collection#count, Collection#slice are issued directly against * the database if the collection is not yet initialized. */ const FETCH_EXTRA_LAZY = 4; 

Thus, setting the appropriate integer solved the problem:

 $query->setFetchMode("MyProject\User", "address", 3); 

Or declare a class with use Doctrine\ORM\Mapping\ClassMetadata at the top, and then use the constant:

 $query->setFetchMode("MyProject\User", "address", ClassMetadata::FETCH_EAGER); 

EDIT:

Since there seems to be a lot of confusion about the right choice of associations, I will edit my answer and add some additional information on how to get the union using my repository.

According to the documentation of the Doctrine, there are 2 types of compounds:

  1. Conventional joins : used to limit results and / or calculate aggregate values.

  2. Retrieve joins: in addition to regular joins: used to retrieve related entities and include them in the hydrated query result.

Thus, in order to get an entity that includes its associations, you will need to โ€œconnectโ€ all these associations to make sure they are loaded with impatience.

I usually donโ€™t use DQL queries to get entities and solve my selective joins; instead, I add my own method to the repository where I use the query designer. This is more flexible and much more readable than using DQL. The correct DQL query will be created by the query builder when the createQuery method is createQuery . You can check the created DQL query, of course, for debugging purposes.

An example of such a custom method in Patientprofile entities from the above question:

 public function findPatientByIdWithAssociations($id)( // create a query builder for patient with alias 'p' $qb = $this->createQueryBuilder('p') ->where('p.id = :patient_id') ->addSelect('pd') ->leftJoin('p.documentation', 'pd') ->addSelect('pa') ->leftJoin('p.address', 'pa') ->setParameter('patient_id', $id); $query = $queryBuilder->getQuery(); return $query->getSingleResult(); } 

And now you can use your own repository method to get the patient by identifier (for example, "555555557"), including links to the documentation and the address of the patient:

 $repository = $this->em->getRepository('Entities\Patientprofile'); $patient = $repository->findPatientByIdWithAssociations('555555557'); 

Make sure you use both addSelect and leftJoin for leftJoin loading.

+11
source

You can use the DQL query:

 $query = $em->createQuery("SELECT p, f FROM Entities\\Patientprofile p JOIN p.Foo f WHERE p.id = ?1"); $query->setParameter(1, 321); $patient = $query->getSingleResult(); 
+5
source

Source: https://habr.com/ru/post/903312/


All Articles