Doctrine: The bright load of lazy relationship relationships?

I use Doctrine 2 to map academic timetables. Here's a simplified view of relationships:

  • a class has events (one-to-many)
    • Event has a type (many-to-one)
    • Event has location (many-to-one)

Using $em->find() , I can get the class only with lazy loads. Or using DQL with joins, I can load the whole graphic object. Is there a solution that is in between?

I want to get a class with lazy-load relationships, and then, under certain conditions, triggers the impatience of loading the relationship of the event and the entire event . Therefore, when I call something like $class->getEventsHydrateAll() , all events of events and events and events will be immediately disabled.

I think I could do this by updating the event schema to indicate the type and location as fetch="EAGER" . But I would like to have control over when this deep hydration occurs.

Here is one attempt I made in my class repository, but Doctrine runs separate queries to search for each type and . .

 $query = $this->_em->createQuery(' SELECT c FROM My\Entity\Class c WHERE c.id = :classId '); $query->setParameter('classId', $classId) ->setFetchMode('My\Entity\Event', 'type', 'EAGER') ->setFetchMode('My\Entity\Event', 'location', 'EAGER'); try { return $query->getSingleResult(); } catch (\Doctrine\ORM\NoResultException $e) { return NULL; } 

Does anyone know if Doctrine supports this? Thanks!

+6
source share
2 answers

TL DR:

You can use the EAGER flag for a class property so that it loads it eagerly. http://doctrine-orm.readthedocs.org/en/latest/reference/annotations-reference.html#manytoone

I'm not sure if this will help you, but I decided it.

First, a little background for my situation. I am currently creating an OAuth 2 implementation on which I want to control small grains by area. The scope is quite granular for (e.g. email, username, etc.), then you can set individual permissions for each of them for reading, creating, editing and deleting.

Here is a database diagram that shows that relationship:

enter image description here

So, my problem was how, for example, I see if a particular token is allowed to read (permission) username (region)?

If I download a token, then I get all its permissions, and then I ask to read it , check the scope of the username , and then a lot of access to the database.

Test code:

 $permissions = $this->getOAuthHelper() ->getAccessToken($accessToken) ->getPermissions(); $results = []; foreach ($permissions as $permission) { $results[] = $permission->getScope()->getTitle(); } return $results; 

Query Log:

 150630 10:49:47 54 Connect root@localhost on api 150630 10:49:51 54 Query SELECT t0.id AS id1, t0.token AS token2, t0.token_expiration AS token_expiration3, t0.refresh AS refresh4, t0.created_at AS created_at5, t0.deleted_at AS deleted_at6, t0.user_id AS user_id7, t0.client_id AS client_id8 FROM oauth_access_tokens t0 WHERE t0.token = 'user-test-token' LIMIT 1 54 Query SELECT t0.id AS id1, t0.access_permission AS access_permission2, t0.scope_id AS scope_id3 FROM oauth_permissions t0 INNER JOIN oauth_access_to_permissions ON t0.id = oauth_access_to_permissions.permission_id WHERE oauth_access_to_permissions.access_id = '1' 150630 10:49:52 54 Query SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '1' 54 Query SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '2' 54 Query SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '3' 54 Query SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '4' 54 Query SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '5' 54 Query SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '6' 54 Query SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '7' 54 Query SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '8' 54 Query SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '9' 54 Query SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '10' 54 Query SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '11' 54 Query SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '12' 54 Query SELECT t0.id AS id1, t0.title AS title2, t0.brief AS brief3, t0.category_id AS category_id4 FROM oauth_scopes t0 WHERE t0.id = '13' 54 Quit 

However, we can see here that the bulk of this is the collection of areas attached to permissions. We can use the fager flag in relation from permission to scope to access areas with permissions:

 /** * @var Scope * * @ORM\ManyToOne(targetEntity="OAuthScope", fetch="EAGER") * @ORM\JoinColumns({ * @ORM\JoinColumn(name="scope_id", referencedColumnName="id") * }) */ protected $scope; 

Note the fetch="EAGER" flag in the ManyToOne annotation.

Now, if we run the same code:

 150630 11:00:06 55 Connect root@localhost on api 150630 11:00:10 55 Query SELECT t0.id AS id1, t0.token AS token2, t0.token_expiration AS token_expiration3, t0.refresh AS refresh4, t0.created_at AS created_at5, t0.deleted_at AS deleted_at6, t0.user_id AS user_id7, t0.client_id AS client_id8 FROM oauth_access_tokens t0 WHERE t0.token = 'user-test-token' LIMIT 1 150630 11:00:11 55 Query SELECT t0.id AS id1, t0.access_permission AS access_permission2, t0.scope_id AS scope_id3, t4.id AS id5, t4.title AS title6, t4.brief AS brief7, t4.category_id AS category_id8 FROM oauth_permissions t0 LEFT JOIN oauth_scopes t4 ON t0.scope_id = t4.id INNER JOIN oauth_access_to_permissions ON t0.id = oauth_access_to_permissions.permission_id WHERE oauth_access_to_permissions.access_id = '1' 55 Quit 
+3
source

I'm not sure, but I think getSingleResult will override hydration mode.

Try โ€œexecuteโ€ instead, as shown in this example: http://docs.doctrine-project.org/en/latest/reference/dql-doctrine-query-language.html#dql-temporarily-change-fetch-mode

-1
source

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


All Articles