ORM

devlop78
Invité n'ayant pas de compte PHPfrance

05 mars 2011, 21:13

Bonjour,

Les ORM tels que Propel et Doctrine m'intéressent. Ce qui m'intéresse surtout c'est le travail implicite qu'ils pourront réaliser. Mais je me pose beaucoup de questions quant à leur fonctionnement.

- Par exemple, lorsque ma base de données contient un champ "UNIQUE", et bien sûr que l'ORM le sait, fait-il bien automatiquement les vérifications avant d'insérer (par exemple) une nouvelle ligne ? J'entends par là, par exemple :
try {
$ligne = new user ();
$ligne->name = "toto";
$ligne->save();
} catch (ORMValidat $e) {
// $e fait référence potentiellement à un problème de l'UNIQUE, pas vraiment une erreur mais
} catch (Exception $e) {
// $e est vraiment une erreur anormale
}
- Par exemple, si je lui dis que "username" doit respecter un masque qui détermine une longueur entre 5 et 10, et seulement alphanumérique, même style de code que précédemment.

Merci par avance, la doc de Doctrine est énorme et en anglais, et je voudrais bien choisir une bonne fois pour toute l'ORM avant de bien me plonger dedans.

ViPHP
ViPHP | 5462 Messages

05 mars 2011, 21:26

il fait tout en fonction du schéma de la base ou du yaml, si ton champs username est réglé en char (10), si il dépasse il va y'avoir une erreur par contre si il fait 2 caractères il va rien dire. Sinon sache que l'ORM est pratique mais prend énormément de ressource dès que tu montes dans le nombre de table ou d'enregistrement.

devlop78
Invité n'ayant pas de compte PHPfrance

05 mars 2011, 21:48

Ressources PHP ou MySQL ? Parce que l'une de mes peurs se trouve justement sur des jointures complexes, je pense qu'il vaut mieux que je reste à la traditionelle plutot qu'il aille me faire 15 requêtes là où moi j'en fais qu'une, même si j'utilise un peu plus de bande passante avec des informations redondantes.

L'un des trucs aussi qui me plaît et que dans mon code je ne gère que très peu, c'est qu'il garde en mémoire les requêtes déjà effectuée pour une même "session". Par exemple, moi je vais utiliser deux fois une méthode pour obtenir des infos à la base (une pour la mise à jour du modèle, l'autre pour la création de la vue), là où lui n'en fera qu'un. En général, je bidouille un peu pour stocker ça ou autre, mais c'est un peu lourd. En plus, je crée une classe par table, avec des méthodes de consultation, de mises à jour etc. Mais c'est un peu lourd à force de créer sans arrêt des SELECT, etc. Pour un projet actuel, je n'ai quasiment aucune validation, l'idée serait d'en faire seulement au niveau Modèle, mais pour une meilleure cohérence et une plus grande rapidité d'écriture, il me faudrait créer des propriétés avec une REGEX pour chaque champs et des méthodes pour vérifier à chaque fois. C'est quand même plus logique et plus sûr que de faire du code de vérif éparpillé partout dans le code. Par contre, à chaque fois que je pense à toutes les améliorations de code, j'ai l'impression que c'est tout simplement un ORM que je m'apprête à créer ...

Et donc, un exemple concret, c'est quand même mieux d'aller faire un $truc = tablebidule->findPK(5); $truc->name = ''; $truc->save(); plutot que de créer une méthode dans une classe tablebidule qui va le faire, une méthode de mise à jour avec des arguments, des validateurs, des exceptions en fonction des validateurs, etc. Pareil pour des insertions ... Je vois donc dans l'ORM tous ces avantages qui sont des méthodes toutes prêtes, des validations si possibles appelées implicitement (validation de type CHECK, Contraintes d'unicité, etc voire contraintes référencielles), ou sinon faciles à créer, des enregistrements BDD et des listes d'enregistrements en mémoire et qui se mettent à jour automatiquement (le rêve serait par exemple la mise à jour d'une liste d'enregistrements qui se met à jour avec la création de nouvelles lignes ou la suppression), etc.

ViPHP
ViPHP | 5462 Messages

05 mars 2011, 22:10

Ressources PHP et MySQL puisque si tu veux juste afficher les infos basique d'un utilisateur, l'ORM va tout prendre, sauf si tu fait tes requêtes personnalisés mais la finalement on arrive à de l'active record.
l'ORM c'est pas un solution miracle qui va faire tout tout seul, et y'a pas de mystère il travaille avec des Models, et si tu veux vérifier l'intégrité de ton username c'est un niveau du model qui faudra l'écrire.
plutot que de créer une méthode dans une classe tablebidule qui va le faire, une méthode de mise à jour avec des arguments, des validateurs, des exceptions en fonction des validateurs, etc. Pareil pour des insertions ...
C'est que fait l'ORM pourtant...
Les Models font tout ce que fait le CRUD par défaut a toi des les adapter après.

devlop78
Invité n'ayant pas de compte PHPfrance

05 mars 2011, 22:25

L'article ici http://www.incapable.fr/conseil-mysql-19 fait vraiment peur. Moi qui ne suis pas attaché à comparer des cycles de processeur sur des fonctions, je suis quand même surpris des résultats. Et effectivement, je n'ai pas toujours besoin d'avoir tous les résultats, et sur l'une des applications sur lesquelles j'ai travaillé, les résultats retournés sont quasiment toujours le fruit d'une requête complexe avec des sous-requêtes, des jointures. En terme de performances, il est clair qu'une appli qui va chercher les FK et fait des requêtes pour faire les jointures serait à pendre.

Par contre, deux questions. Pourquoi, si l'ORM n'est pas si avantageux, est-il utilisé dans les frameworks. J'ai toujours été surpris de voir de grosses applications tourner sur des frameworks tels que Symfony, véritable monstre. Je n'ose même pas imaginer le nombre d'include nécessaires.

La deuxième est : quels sont les outils intermédiaires sur lesquels je pourrais me reposer. Si l'ORM ne s'avère pas être LA solution, on a déjà un bon début avec PDO_FETCH_OBJECT, par exemple. On peut imaginer rajouter une méthode save() etc, mais sans réinventer toute la roue, quels outils (je ne connais pas les termes) peuvent venir aider sur les validations (pas PEAR.validation hein :p), la lecture, et la modifications d'enregistrements ... ?

devlop78
Invité n'ayant pas de compte PHPfrance

05 mars 2011, 22:41

R pas un solution miracle qui va faire tout tout seul, et y'a pas de mystère il travaille avec des Models, et si tu veux vérifier l'intégrité de ton username c'est un niveau du model qui faudra l'écrire.
Bien sûr, pour propel, c'est un tag XML où l'on précise les contraintes. Là dessus, rien à dire, un simple test de validation contrôle toutes les données.

Par contre, pour certaines applications, les jointures sont peu fréquentes même si les relations sont nombreuses. Ecrire, lors de ces jointures, sont propres code (ou avec l'outil disponible), ce n'est pas grave. En fait, ce n'est pas tant dans la lecture que c'est problématique. Car actuellement, mes méthodes de lectures renvoient un tableau avec les lignes et les colonnes. Donc, au niveau du code qui appelle cette méthode de mon code modèle, il est bien obligé de connaître le nom des champs utilisés dans la bdd. L'ORM a au moins l'avantage de simplifier la plupart des codes, et de ramener une liste de "record" sous forme d'objet. Ce qui est bien plus agréable à travailler qu'un tableau. Si je dois démarrer dessus avec PDO, je vais devoir créer des classes à gogo, dont une classe de type RecordList itérable ... bref ...

L'un des atouts, est quand même le save(). Sur une des appli que j'ai, en gros, je prends les valeurs d'une ligne d'une table, l'utilisateur modifie, et j'enregistre. Actuellement j'ai un SELECT pour prendre ces valeurs. C'est rapide à faire, mais si un outil peut me permettre de le faire plus rapidement ... ensuite, je dois récupérer la valeur de l'utilisateur ... bon $_POST, rien ne changera. Ensuite, je dois transmettre cette valeur à ma classe de table, qui doit controler chaque champs (actuellement, peu de controles effectués car je regarde des solutions justement), émettre des exceptions éventuellement, et faire un UPDATE.

Mon idée avec l'ORM, est de simplement aller chercher cette ligne sous forme d'objet. De modifier chaque propriété de l'objet, en attrapant éventuellement des exceptions, puis de faire un petit ... save(). Bien sûr, derrière la déclaration des tables, des contraintes etc doit etre faite. Mais le reste parait bien plus automatique.

Donc je me renseigne un max sur des retours d'expérience, sur les performances (je suis bien conscient que c'est plus gourmand, mais il ne faut pas abuser), et si ça répond à mes besoins.

;)

ViPHP
ViPHP | 5462 Messages

05 mars 2011, 22:54

L'ORM simplifie le développement dans le sens ou c'est déjà (et bien) fait. Il peut être utilise avec le Zend Framework et Symfony. Mais tout depend de l'application final c'est comme le choix d'un SGDB.
En outils interne a PHP PDO propose le FETCH_CLASS qui est vraiment pas mal, faire un mini ORM avec PDO c'est très simple, par contre PDO n'est qu'une abstraction de base de donnée, donc il faut écrire les requêtes pour chaque SGBD (ce que fait déjà Doctrine)

devlop78
Invité n'ayant pas de compte PHPfrance

05 mars 2011, 23:04

L'application dans laquelle je souhaite l'intégrer (au boulot, hors de question de recoder ...) va servir d'objet de mémoire, en quelque sorte, pour l'obtention de mon diplôme. Il est effectivement intéressant de regarder pour le coder moi-même.

Par contre, quelqu'un connait-il des articles justement sur le fonctionnement de ces ORM (par rapport aux problématiques posés ici-même), et leurs performances. Car pour moi, un outil trop lourd, c'est un outil que je ne pense pas utiliser. L'article que j'ai posté tout à l'heure est intéressant, toutefois, il parait que Doctrine 2 est véritablement plus rapide que les versions antérieures. Je ne peux pas les utiliser car je n'ai pas PHP 5.3 en production, mais ce n'est pas un problème : à l'heure actuel, les performances sur mon application ne sont pas tellement importantes. C'est surtout que je ne souhaite pas m'investir dans l'étude d'un outil qui ne répondra pas aux critères d'applications futures. Mettre que je connais bien Doctrine ou Propel dans un CV, c'est toujours bien, mais si c'est pour me dire au final qu'il est inutilisable ... ça sert à rien :oops:

ViPHP
ViPHP | 5462 Messages

05 mars 2011, 23:14

C'est que je te dis tout dépend du projet, c'est un peu le même débat que l'utilisation d'un framework, tu peux nous décrire l'application et on peut t'orienter vers tel ou tel outils.

devlop78
Invité n'ayant pas de compte PHPfrance

06 mars 2011, 02:11

Je vais prendre quelques heures et faire les tests moi-même. Merci Stealth pour ta participation. Si d'autres ont des commentaires :)

devlop78
Invité n'ayant pas de compte PHPfrance

07 mars 2011, 02:32

Bon, je me suis mis à Propel, et je ne suis pas déçu :)

Donc, avantages, déjà la rapidité d'écriture. Ensuite, Propel plutôt que Doctrine pour les validateurs. Doctrine en possèdent mais il ne parait pas possible de savoir quel contrainte a été violée. Pour Propel, une contrainte de validation = un message. Ainsi, il est facile d'écrire "le nom d'utilisateur doit etre compris entre 10 et 15 caractères", et hop, on peut injecter le message partout :p Gros avantages si un jour on veut changer cette règle.

Ensuite, dans le XML on peut déclarer un champs comme unique. Je l'avais fait coté base de données, et j'ai eu une exception PDO. C'est super. Avec les validations, c'est Propel qui va vérifier avant et renvoie une erreur Propel. On peut donc dissocier "l'erreur" ou plutot la violation de validation Propel de l'erreur PDO.

Ensuite, un objet créé par exemple, on accède facilement à son identifiant généré. Si on fait une recherche d'une ligne à partir de cet identifiant, Propel nous retourne le même objet que celui créé. On a donc une seule instance, ce qui est cohérent. Pareil pour les listes, elles se mettent à jour en cas d'ajout ou de suppression, alors même que l'on ne le communique pas à la liste. Il faudra que je fasse les tests en cas de suppression en CASCADE de bdd, bien sûr en le déclarant.

A l'instant, je viens de regarder (et c'était l'une de mes interrogations) deux choses : charge-t-il les références à la création de l'instance, ou à l'appel de l'accesseur approprié. C'est superbe, il ne le fait qu'à l'appel de l'accesseur. Donc une liste de livres pour un auteur donné ne se charge pas à la recherche d'un auteur.

La deuxieme chose : peut-on lui demander de ne pas chercher tous les champs pour une ligne. La réponse non testée mais indiquée dans la documentation : oui. C'est le "lazyLoad". Ainsi, le champs n'est cherché que lorsque l'accesseur est appelé. Ce qui m'arrange par exemple pour l'application actuelle où un champs mediumText est présent. Je n'en ai pas besoin tout le temps, et ce serait du gachis de bande passante que de d'aller le chercher. En réalité, c'est plus compliqué : j'ai besoin de savoir s'il est NULL ou pas. Propel gère des "behaviors" d'aggrégation etc, donc j'imagine qu'il y a moyen de créer un champs virtuel qui stockera cette info. Sinon, ce sera une requête sur-mesure.

Bref, partant du principe que des gros sites utilisaient des frameworks certainement assez gourmands (ils ne doivent pas se contenter de charger trois petites classes) avec des ORM, je peux moi aussi me le permettre pour mon application avec 2 personnes par jour ;p. Eventuellement, si on s'appelle Google, le framework n'est pas tellement approprié ...

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

07 mars 2011, 10:57

Là où j'ai eu le plus de soucis avec Propel, c'est pour le chargement de résultats de jointures : Propel n'hydrate que la classe de base, mais pas les résultats liés, et je devais hydrater moi-même les objets annexes.
Toutefois, comme je suis passé à Doctrine depuis plusieurs années, je ne sais pas si ça a été corrigé depuis.
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

devlop78
Invité n'ayant pas de compte PHPfrance

07 mars 2011, 20:42

Je pense que beaucoup de choses ont changés en quelques années. PhP a lui-même bien évoluer, ça peut sembler hors sujet, mais je pense que ces applications ont tardé à murir.

Propel me semble vraiment bien, et peut-être que Doctrine 2 répondrait mieux à mes besoins, malheureusement pour l'application courante, elle n'y répond pas. Et comme je l'avais exprimé, mon besoin n'est pas de la performances, "gâcher" des millisecondes n'est pas un problème. C'est l'ORM en lui-même qui me fait doûter, je suis assez partagé. Propel m'a bien convaincu, mais quand je regarde mes codes, j'ai comme une nostalgie. Et pourtant, la plupart ne nécessite pas d'être protégés, mais pour les autres, la lourdeur est une horreur. C'est donc à étudier, si l'ORM apporte vraiment, ou si de plus petites briques, surtout celle de la validation, sont plus appropriées. Je suis enchanté des raccourcis de l'ORM mais à la fois j'ai peur qu'il ne m'apporte que plus de complexité, et le fait de ne pas maitriser le SQL qu'il génère m'angoisse aussi. Je fais souvent des requêtes SQL complexes, et l'ORM ne m'apportera rien là, il risque même de me perturber dans mes reflexions. Parallèlement, il oblige dès le départ à modéliser ses informations, ce qui est une très bonne chose.

Tout ça manque donc pour moi d'expérience, et j'ai peur que sans grand Maître Yoda, je ne sois obligé de me casser quelque peu les dents pour en tirer toutes les leçons ;)

devlop78
Invité n'ayant pas de compte PHPfrance

07 mars 2011, 20:52

Lol, le pire c'est que d'avoir écrit ce dernier post m'a encore plus fait douter : en lecture, j'ai des requêtes souvent complexes, donc un objet s'adaptant à tous les champs est plus approprié à un objet pré-formatté. A coté, en écriture, j'ai rarement besoin de charger toute une ligne pour mettre à jour une valeur ... Bref ... ça sent l'ORM maison ça ... avec validations, hydratation très souple résultant de la requête, mise en forme automatique des valeurs (si la variable php === null, alors ce sera NULL en SQL et non '', etc, ce que je fais actuellement avec du terniaire).

J'ai besoin de retour d'expériences, pleeeeaaasse 8-|