Bonjour,
Je suis confronté à un problème qui m'avait l'air trivial mais qui me pose plus de problèmes que prévu (du moins en PHP).
J'ai un jeu de résultats potentiellement très grand, provenant d'une jointure SQL one-to-many (triée par ID de la partie "one"), dans un itérateur de sorte à ce que tout ne soit pas chargé en mémoire. Un exemple de résultat : https://wall.deblan.org/x1baa/php/1/
L'idée est de créer un itérateur PHP qui (dans l'exemple) aggrège les colonnes `name` dans un tableau `names` jusqu'à un changement d'`id`.
Le résultat devrait être le suivant après un `iterator_to_array` : https://wall.deblan.org/x1bab/php/1/
J'ai implémenté ça sans problèmes avec un générateur PHP 5.5, et ça marche très bien: https://wall.deblan.org/x1bac/php/1/
Mais le serveur de production est en PHP 5.4, et faut pas compter avoir PHP 5.5 dessus avant que ce soit la version par défaut sur Debian stable. Je me retrouve donc à devoir implémenter une logique similaire dans une classe qui implémente `Iterator`, et là je bloque. Y'a beaucoup plus de contraintes "inutiles" que je n'avais pas avec le générateur, et je ne trouve pas de solution qui me semble logique et évidente.
J'ai essayé d'observer comment fait Laravel, mais il s'avère qu'ils chargent le résultat entier en mémoire pour gérer les associations : https://github.com/illuminate/database/blob/8de434dbdd352b271201eb537df5f629060f4ea7/Eloquent/Relations/BelongsToMany.php#L390-L439
J'ai aussi regardé du côté de Doctrine qui a une méthode `iterate` pour ne pas tout charger en mémoire, mais cette méthode est justement incompatible avec les jointures de ce type (voir la note en jaune sur la doc) : http://docs.doctrine-project.org/en/2.0.x/reference/batch-processing.html#iterating-results
Enfin, j'ai regardé des solutions équivalentes en JavaScript, en particulier une réponse sur StackOverflow qui monte un exemple de "simulation de yield" avec Traceur, mais le résultat compilé est incompréhensible et dépend en plus sur le runtime de Traceur : http://stackoverflow.com/a/14095322
J'ai pas l'impression que le fait d'itérer sur des relations one-to-many est quelque chose d'exceptionnel, c'est apparemment la méthode la plus efficace pour éviter le problème des N+1 requêtes : http://use-the-index-luke.com/sql/join/nested-loops-join-n1-problem
Ce qui est peut-être moins commun, c'est de factoriser la logique dans un itérateur pour rendre l'aggrégation transparente au code final qui va itérer sur les résultats.
Avez-vous déjà rencontré ce problème ? Quelles solutions, patterns, outils, librairies utiliser pour résoudre le problème sans les générateurs PHP 5.5 ?