Je viens de mettre à dispo sur sourceforge une API php5 qui permet de manipuler les résultats d'une base mysql en les transformant en objets.
En gros, dynamiquement ça récupère les tuples d'un select avec des jointures, les sectionne et crée des objets qui hérite nt des attributs de chaque table.
C'est juste un essai d'implémentation d'une interface que j'avais écrit. Ca n'est pas foncièrement utile mais bon on ne sait jamais...
https://sourceforge.net/projects/phpmyobject/
Si vous avez des idées d'améliorations, contactez moi en privée, je vous donnerais un accès sur le cvs.
# Soucis
Posté par Raphaël G. (site web personnel) . Évalué à 2.
Sinon quel est l'utilisation et son intérêt ?
Moi ce que j'aimerais avoir un jour serait un pdo vraiment complet pour toutes les dbs (enfin pgsql/mysql/sqlite)
Qu'on puisse appeler comme une classe.
(avec si possible de la cache et autre)
[^] # Re: Soucis
Posté par raj deenoo . Évalué à 3.
[^] # Re: Soucis
Posté par Code34 (site web personnel) . Évalué à 1.
l api n'est pas complète, mais bon ça fait clairement pas ce qui t intérresses. C'est pas comme une class qui implémenterait jdbc:odbc. C'est pas non plus comme pear.
l'exemple d'utilisation est dans la test class. Une fois que t as renseigné les paramêtres mysql, Tu peux récupérer n''importe quel enregistrement d'une de tes tables et le manipuler comme un objet.
Par exemple
tu passes un "select * from db_user, db_ville limit 1" à ton controleur.
Il va te créer deux objets disctints(c'est ça l'essentiel) user et ville que tu peux manipuler avec les getter et setter.
Pareil si tu fais une jointure avec plus de 2 tables.
genre:
$object->getAttribute('user_login') va te sortir le nom de ton user.
etc ...
[^] # Re: Soucis
Posté par nanard . Évalué à 1.
Avec ce type de programmation, ne plus écrire de lourde requêtes sql c'est un réel plaisir. ( je me doute que tu n'en ai pas encore arrivé la ) je me mets ca dans un coin voir comment ca fonctionne et si ca peut m'être utile toussa.
Allez tous vous faire spéculer.
[^] # Re: Soucis
Posté par Code34 (site web personnel) . Évalué à 1.
Mon projet était en premier lieu de concevoir une interface, et ensuite de l'implémenter .
Je ne pense pas que je refasse de mise à jour, ou que je maintienne cette API.
La seule chose que je vais apporter à court terme c'est:
- une contrainte sur l'unicité des primary keys pour qu'un objet soit unique,
- que chaque objet soit classé dans une map en fonction de son type (et non plus dans une seule map)
- implémenter la méthode pour updater les tables sql.
- peut être et la c'est du domaine du rêve, implémenter un système relationnel objet
[^] # Re: Soucis
Posté par Moogle . Évalué à 2.
[1] http://propel.phpdb.org/
[^] # Re: Soucis
Posté par Code34 (site web personnel) . Évalué à 1.
$book = BookPeer::retrieveByPK(5);
$book->setTitle('The Propel Story');
$book->save();
ça y ressemble. Sauf que ça me semble plus lourd à gérer. En fait, mon api gère elle même dynamiquement le nom des attributs.
exemple t as une table
book
====
titre
auteur
le code équivalent à ce qui est écrit au dessus serait:
$book ->setAttribute('titre', 'The Propel Story');
$book->setAttribute('auteur', 'toto');
$book->save(); (non implémenté)
L'intérêt est donc la dynamique étant donné qu'il n'y a pas de getter/setter à écrire.
Mais bon le truc le plus important c'est pas la manipulation des attributs, c'est la gestion des jointures de pouvoir créer plusieurs objets qui correspondent aux différentes tables à partir d'une seule ligne résultat.
La problèmatique est que SQL ne renvoit pas la provenance des résultats en fonction des tables.
[^] # Re: Soucis
Posté par Mathieu CLAUDEL (site web personnel) . Évalué à 1.
(http://www.phpdoctrine.net/doctrine/manual/documentation2.ph(...)
[^] # Re: Soucis
Posté par Code34 (site web personnel) . Évalué à 1.
Le postulat de base concernant l'utilisation de cette api est de considérer chaque enregistrement contenu dans une seul table comme un objet.
Si tu fais un select sur deux tables jointes, tu récupères une seule ligne de résultat.
Hors si le résultat provient de deux tables à la fois, le seul objet que tu vas créer ne peut être considéré comme un objet enregistrement.
L'api pour chaque ligne de résultat va donc créer autant d'objets distincts qu'il y a de tables.
Je prend un exemple
select * from db_user, db_town limit where db_user.id_town=db_town.id_town 1;
avec
db_user
=======
id _user = 1
user_nom = toto
id_town = 1
et
db_town
=======
id_town = 1
town_nom = toulouse
le résultat de la requête sql va être:
id_user user_nom user_ville id_town town_nom
1 toto 1 toulouse
l'api va donc crée 2 objets distincts et non un seul.
Un objet db_user qui a comme attribue les noms de la champs de la table db_user, et un objet db_town qui a les attributes de la table db_town
[^] # Re: Soucis
Posté par Laurent J (site web personnel, Mastodon) . Évalué à 2.
Ce qui est en contradiction avec ton doux rêve de mapping relationnel objet. Comme je dis dans un commentaire plus bas, le mapping objet ne se résume pas à une table = un objet, mais il est normalement possible de faire plusieurs tables = un objet.
[^] # Re: Soucis
Posté par Code34 (site web personnel) . Évalué à 1.
Oui c'est possible c'est le comportement par défaut de la fonction php5 mysql_fetch_object
http://fr.php.net/manual/fr/function.mysql-fetch-object.php
qui te renvoit chaque tuple sous la forme d'un seul et unique objet...
Ca n'a donc pas d'intérêt de développer une api qui fasse cela.
[^] # Re: Soucis
Posté par Laurent J (site web personnel, Mastodon) . Évalué à 2.
Mouai. Alors d'une part, je trouve plus simple d'écrire
$book->setTitle('The Propel Story');
Plutôt que
$book ->setAttribute('titre', 'The Propel Story');
Ensuite, tu as du raté quelque chose en PHP5, ce sont les méthodes magiques __getter__ et __setter__ qui peuvent t'éviter d'écrire des methodes setters et getters ;-)
D'où l'utilisation avec jDao, dans mon framework Jelix, d'un fichier XML qui explicite le mapping à faire. Cela permet ensuite à jDao de compiler à la volée des classes PHP (et les requêtes qui vont avec) et de savoir à jDao quel champs appartient à quelle table. (et je précise que le fichier XML peut être généré directement à partir de la table via un script en ligne de commande). http://jelix.org/articles/tutoriel/utiliser-dao .
Cela a aussi l'avantage d'implémenter en partie ce que tu appelle du domaine du rêve dans un commentaire précédent : un système relationnel objet.
En effet, faire du mapping objet, ce n'est pas seulement faire "une table = un objet" (sinon ça sert pas à grand chose, autant utiliser l'api proposée par PHP : http://fr.php.net/manual/fr/ref.mysqli.php qui manipule des objets), mais plusieurs tables = un objet. Bref, permettre la possibilité qu'un objet tire ses informations de plusieurs tables à la fois.
[^] # Re: Soucis
Posté par Code34 (site web personnel) . Évalué à 2.
Avoir des méthodes setTitle cela sous entend que tu vas avoir des classes différentes pour chaque type d'objets embarquant leurs propres méthodes pour manipuler les attributs.
Ici, t'as une seule classe mère tuple qui possède donc les deux méthodes, + simple + élégant après tu peux bien entendu créer des classes filles avec des méthodes setTitle, mais ça n'a aucun intérêt car la class mère à la capacité de le faire.
L'utilité de manipuler des objets distincts est de pouvoir ensuite modifier , et enregistrer les objets ensuite dans la base.
Avec la méthode générique , extraire une ligne et la considérer comme un seul objet, c'est dans l'optique de l'afficher.
De même si tu modifies la valeur d'un de tes attributs, tu seras contraint d'opérer directement la modification sur la base via un update et c'est mal !
[^] # Re: Soucis
Posté par Laurent J (site web personnel, Mastodon) . Évalué à 3.
Il me semble que ce que tu décris est déjà implementé. En tout cas, dans mon framework Jelix, je récupère bien des objets avec PDO, et mieux encore, des objets qui sont instanciés avec la classe que je veux. (regarde PDOStatement::setFetchMode et les paramètres de PDOStatement::fetch() ;-) )
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.