Bonjour,

Ma question est assez compliquée à expliquer et je vais essayer d'être le plus clair possible. Je remercie d'avance les personnes qui prendront le temps d'y répondre!

Je cherche à approfondir mes connaissances concernant le fonctionnement interne des ORM, et en particulier leur façon de contourner donc le problème d'extraction imbriquée (problème d'extraction N+1) posés par une (mauvaise) utilisation de ces solutions.

J'ai noté que certains ORMs comme Nextras\ORM, LessQL, Gas ORM ou NotORM disent envoyer un nombre de requêtes constant quelle que soit l'utilisation faite de l'objet retourné, éliminant en conséquence tout problème d'extraction imbriquée, et ce sans avoir besoin de définir manuellement quand utiliser le eager loading comme le font beaucoup d'ORMs (exemple: Doctrine qui permet d'utiliser FETCH=EAGER).

Voici l'explication donné par Nextras\Orm sur leur site :

Nextras\Orm uses constant number of queries: it does not matter, how much data you will ouput or how many inner cycles you will use. Orm will fetch all needed data in advance. Let's see an exmaple:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
$authors = $orm->authors->findAll();
foreach ($authors as $author) {
    echo $author->name;
 
    foreach ($author->books as $book) {
        echo $book->title;
        echo $book->translator->name;
 
        foreach ($book->tags as $tag) {
            echo $tag->name;
        }
    }
}
The code above will run 4 queries:

to select all the authors,
to select all books which were authored by previously selected authors,
to select all translators who translated the previously selected books,
to select all tags for previously selected books.

As you can see, Orm will not query in each cycle pass, rather it will query all the needed data at once.
J'aime beaucoup le principe, ça semble très intuitif... Mais COMMENT CA MARCHE??? J'ai tenté de regarder le code de ces outils, mais je n'arrive pas trouver la réponse

D'après ce que j'ai compris, il y a bien un lazy loading et par exemple les différents livres contenus par la variable "books" ne seraient chargés qu'au moment où la ligne foreach ($author->books as $book) est appelée. Cependant, au lieu de ne charger que les livre d'un auteur spécifique ($author), ce lazy loading chargerait tous les livres de tous les auteurs retournés en début de script (via le findAll()).

C'est là que je suis perdu : comment une quelconque fonction de $author, qui ne représente qu'un auteur spécifique et non l'ensemble des auteurs retournés par le findAll(), peut modifier l'ensemble des objets auteurs afin d'y charger les livres? Via une variable statique de classe qui contiendrait l'ensemble des livres écrits par les auteurs retournés? Via l'appel dans $author de $orm->authors afin de modifier tous les objets?

Merci d'avance de vos lumière. J'ai du loupé un truc tout bête, mais impossible de trouver quoi!

Lionel