Forum Programmation.php J'ai besoin d'un avis extérieur pour m'aider...

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
4
18
juil.
2016

Bonjour à tous,

Je suis encore en train de reprendre un code qui ne m'appartient pas, et je suis peut être (sans doute?) en train de faire de la merde…

Pour me débarrasser d'un fichier de fonctions énorme et impossible à maintenir sans efforts démentiels, j'ai chercher à rassembler dans des classes toutes les fonctions liées à un type de données. Par exemple, j'ai une classe "utilisateur" avec un nom, prenom, adresse, CP, ville.

Dans l'ancien code, lorsqu'on voulait tous les utilisateurs d'une ville données, une fonction faisait la requete SQL ("select * from utilisateurs where ville = 'paris'), et renvoyais directement le resultSet. Charge ensuite à la page PHP de traiter les enregistrements :

while($row = mysqli_fetch_array($result)) {
...
}
C'est clairement la manière de faire qui me semble être la plus optimale, sauf que j'aimerais vraiment (mais alors vraiment) séparer l'interface avec les traitements issus de la base de données.

j'ai donc créé une fonction statique qui renvoie un tableau d'objet "utilisateur". Ca fonctionne, ça à l'air pas mal, sauf qu'au niveau performances, c'est juste pas possible !!! En gros, je fais une première requête pour récupérer les identifiants des utilisateurs concernés (select id from utilisateurs where ville = 'paris'), et ensuite, je crée une instance (utilisateur = new utilisateur(id) ) pour chaque utilisateur que je stocke dans un tableau, qui est finalement retourné par la fonction. Sauf que forcément, chaque appel à "new utilisateur(id)" me refait une requête SQL…

Si fonctionnellement, je trouve ça plus élégant, au niveau performance, je transforme quelque chose qui fait une seule requête et qui traite ligne par ligne, par quelque chose qui fait n+1 requêtes (suivant le nombre d’utilisateurs), qui fait une première boucle pour stocker ça dans un tableau, et qui fait encore une deuxième boucle pour faire l'affichage ! Sur-consommation de mémoire et de temps CPU !

Et toi cher journal, comment me conseilles tu de régler le problème ?
```

  • # Proxy de données

    Posté par  . Évalué à 5.

    Le cadriciel Symfony utilise la notion de proxy de données pour éviter cette cascade qui fait chuter les performances. L'idée est qu'on n'instancie l'objet que quand on y touche réellement.

    Donc tu instancies seulement des proxys d'utilisateur, qui eux ne font pas de requete SQL…

    ⚓ À g'Auch TOUTE! http://afdgauch.online.fr

    • [^] # Re: Proxy de données

      Posté par  . Évalué à 1.

      J'avoue, je ne comprends qu'à moitié la réponse… Si on instancie quand on y touche, alors ça arrive dès qu'on veut l'afficher, non ?

      Ce que je comprends en revanche, c'est que j'ai déjà du mal à faire des modifications dans le code sans trop foutre en l'air l'existant, alors de là à utiliser un nouveau framework, je crois que c'est pas pour tout de suite !

      Je vais quand même regarder cette notion de "proxy", on ne sait jamais, ca pourrait me donner des idées.

      merci !

  • # Une classe "ensemble d'utilisateur"

    Posté par  . Évalué à 2.

    Moi pour commencer, je ferai une classe utilisateur et une classe "ensemble d'utilisateur" qui serait une liste ou un ensemble d'instance d'utilisateur. Cette classe aurait une méthode (surement un constructeur même) qui permettrait de générer la liste et d'instancier tous les utilisateurs à partir d'un critère de recherche/une requête SQL et donc en ne faisant qu'une requête.

  • # Commentaire supprimé

    Posté par  . Évalué à 3.

    Ce commentaire a été supprimé par l’équipe de modération.

    • [^] # Re: constructeur privé et méthodes statiques

      Posté par  . Évalué à 1.

      Merci pour ces conseils. J'en arrivais à peu prêt à la même conclusion : ma méthode getUserByVille est déjà statique, seulement, je ne voyais pas forcément comment créer mes objets derrière… Il va sans doute falloir que je créé un constructeur spécifique qui créé l'objet sans faire de requête, mais avec un tableau de données déjà prêt (mysqli_fetch_array par exemple).

      Merci pour toutes vos réponses.

  • # Paramêtre dans ta fonction de récupération

    Posté par  . Évalué à 2. Dernière modification le 19 juillet 2016 à 21:50.

    Un moyen simple serait d'ajouter un paramètre "préchargement" à ta fonction de récupération qui si il est passé à true va en plus de te renvoyer les ids de tes utilisateur effectuer la récupération des donnés et charger tes objets utilisateurs comme des singleton en mémoire.
    Cela peut aussi se faire avec une seconde méthode prenant une liste d'ids. Dans ce cas cela fera deux requêtes mais c'est déjà beaucoup mieux que une par utilisateur.
    Lors de l'instanciation ultérieure de tes objets il seront déjà chargés en mémoire avec leurs données.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.