Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

CLASS ABSTRACTION MYSQL (ORM)


Information sur la source

Catégorie :Base de données Classé sous : pdo, orm, abstraction, mysql, singleton Niveau : Initié Date de création : 09/08/2008 Date de mise à jour : 10/08/2008 23:39:13 Vu / téléchargé: 2 605 / 90

Note :
Aucune note

Commentaire sur cette source (11)
Ajouter un commentaire et/ou une note

Description

surcouche pdo, abstraction de la syntaxe des requetes sql et des tables
ça ressemble un petit peu (mais de loin) à un orm
Php5 est donc requis, fonctionne avec mysql uniquement ... pour le moment ...  
tout est dans le zip

 

Source

  • <?php
  • # initialisation bdd
  • $Db=SqlDb::connect($Db_Conf['id'],$Db_Conf['host'], $Db_Conf['User'] , $Db_Conf['pass'], $Db_Conf['base']);
  • // dossier contenant la config des tables
  • $Table = new SqlTable('./default/');
  • // ------------------------------------------------
  • // exemple d'un module de news
  • class actualite extends Module {
  • private $Table;
  • public function __construct() {
  • $this->Table = new Sql('module.actualite');
  • }
  • public function ajouter($user,$categorie,$sujet,$texte,$image) {
  • $values=array(':id',':user',':date',':categorie',':sujet',':texte',':image');
  • $insert=$this->Table->insert();
  • $insert->values($values);
  • $query = $insert->prepare();
  • $query->bindValue(':id','');
  • $query->bindValue(':user',$user);
  • $query->bindValue(':date',time());
  • $query->bindValue(':categorie',$categorie);
  • $query->bindValue(':sujet',$sujet);
  • $query->bindValue(':texte',$texte);
  • $query->bindValue(':image',$image);
  • $query->execute();
  • return $query->rowCount();
  • }
  • public function modifier($id,$user,$time,$categorie,$sujet,$texte,$image) {
  • $update=$this->Table->update();
  • $update->where('id',':where','=');
  • $update->set('id',':id');
  • $update->set('user',':user');
  • $update->set('date',':date');
  • $update->set('categorie',':categorie');
  • $update->set('sujet',':sujet');
  • $update->set('texte',':texte');
  • $update->set('image',':image');
  • $query=$update->prepare();
  • $query->bindValue(':where',$id);
  • $query->bindValue(':id',$id);
  • $query->bindValue(':user',$user);
  • $query->bindValue(':date',$time);
  • $query->bindValue(':categorie',$categorie);
  • $query->bindValue(':sujet',$sujet);
  • $query->bindValue(':texte',$texte);
  • $query->bindValue(':image',$image);
  • $query->execute();
  • return $query->rowCount();
  • }
  • public function supprimer($id) {
  • $delete=$this->Table->delete();
  • $delete->where('id',':id','=');
  • $query=$delete->prepare();
  • $query->bindValue(':id',$id);
  • $query->execute();
  • return $query->rowCount();
  • }
  • public function afficher($begin='0',$end='2') {
  • $select = $this->Table->select('id,user,sujet,texte,categorie');
  • $select->where(1);
  • $select->limit($begin,$end);
  • $query=$select->prepare();
  • $query->execute();
  • $nb_item = $this->nb_actualite();
  • $this->pagination($begin,$end,$nb_item);
  • while ($mfa= $query->fetch() ) {
  • $r['ACTUALITE'][]=$mfa;
  • }
  • return $r;
  • }
  • ...
  • // autre exemple sans utiliser les méthodes objets
  • class Account {
  • private $Table;
  • public function __construct() {
  • $this->Table = new Sql('core.User');
  • }
  • public function userExist($user) {
  • if ( isPseudo($user) ) {
  • $q=$this->Table->query("SELECT id,user,mail,pass FROM ".$this->Table->name." WHERE user = '$user' limit 0,1");
  • return $q->fetchAssoc();
  • }
  • return false;
  • }
  • public function userInfo($user) {
  • $q=$this->Table->query("SELECT * FROM ".$this->Table->name." WHERE user='$user' limit 0,1");
  • return $q->fetchAssoc();
  • }
  • ...
  • ?>
<?php
# initialisation bdd
$Db=SqlDb::connect($Db_Conf['id'],$Db_Conf['host'], $Db_Conf['User'] , $Db_Conf['pass'], $Db_Conf['base']);

// dossier contenant la config des tables 
$Table = new SqlTable('./default/');

// ------------------------------------------------
// exemple d'un module de news 

class actualite extends Module {
    private $Table;
    
    public function __construct() {
      $this->Table = new Sql('module.actualite');
    }
    
    public function ajouter($user,$categorie,$sujet,$texte,$image) {
       $values=array(':id',':user',':date',':categorie',':sujet',':texte',':image');
       $insert=$this->Table->insert();
       $insert->values($values);
       
       $query = $insert->prepare();
       $query->bindValue(':id','');
       $query->bindValue(':user',$user);
       $query->bindValue(':date',time());
       $query->bindValue(':categorie',$categorie);
       $query->bindValue(':sujet',$sujet);
       $query->bindValue(':texte',$texte);
       $query->bindValue(':image',$image);
       $query->execute();
       return $query->rowCount();
    }
    
    public function modifier($id,$user,$time,$categorie,$sujet,$texte,$image) {
    
       $update=$this->Table->update();
       $update->where('id',':where','=');
       $update->set('id',':id');
       $update->set('user',':user');
       $update->set('date',':date');
       $update->set('categorie',':categorie');
       $update->set('sujet',':sujet');
       $update->set('texte',':texte');
       $update->set('image',':image');
       $query=$update->prepare();
       
       $query->bindValue(':where',$id);
       $query->bindValue(':id',$id);
       $query->bindValue(':user',$user);
       $query->bindValue(':date',$time);
       $query->bindValue(':categorie',$categorie);
       $query->bindValue(':sujet',$sujet);
       $query->bindValue(':texte',$texte);
       $query->bindValue(':image',$image);
       $query->execute();
       return $query->rowCount();
    }
    public function supprimer($id) {
       $delete=$this->Table->delete();
       $delete->where('id',':id','=');
       
       $query=$delete->prepare();
       $query->bindValue(':id',$id);
       $query->execute();
       return $query->rowCount();
    }
    
    public function afficher($begin='0',$end='2') {
       $select = $this->Table->select('id,user,sujet,texte,categorie');
       $select->where(1);
       $select->limit($begin,$end);
       
       $query=$select->prepare();
       $query->execute();
       $nb_item = $this->nb_actualite();
       $this->pagination($begin,$end,$nb_item);
       
       while ($mfa= $query->fetch() ) {
         $r['ACTUALITE'][]=$mfa;
       }
       return $r;
   }
   ...
// autre exemple sans utiliser les méthodes objets 

class Account {
  private $Table;
  public function __construct() {
      $this->Table = new Sql('core.User');
  }
  public function userExist($user) {
     if ( isPseudo($user) ) {
         $q=$this->Table->query("SELECT id,user,mail,pass FROM ".$this->Table->name." WHERE user = '$user' limit 0,1");
         return $q->fetchAssoc();
      }
      return false;
  }
  
  public function userInfo($user) {
      $q=$this->Table->query("SELECT * FROM ".$this->Table->name." WHERE user='$user' limit 0,1");
      return $q->fetchAssoc();
  }
  ...
?>

Conclusion

La source n'est pas finis, mais exploitable
je la partage, pour donner des idées, avoir des retours et l'améliorer
 

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

Historique

09 août 2008 21:26:49 :
précision sur la source
10 août 2008 20:02:44 :
précision sur la source
10 août 2008 23:39:13 :
correction

Commentaires et avis

signaler à un administrateur
Commentaire de neigedhiver le 09/08/2008 20:24:57

Salut,

Quand j'ai vu le titre de la source, je me suis dit : "Mais pourquoi encore faire de l'abstraction, au lieu d'utiliser PDO ?".
Bon, tu utilsies PDO, donc bon...

Alors j'ai vaguement regardé, et j'ai pas bien compris...
Je vois que t'as des classes qui s'appellent SqlMysqlDelete, par exemple... Et là, je ne comprends pas l'intérêt d'utiliser PDO, si c'est pour faire des classes pour du MySQL...
Notamment, tu utilises la clause LIMIT, qui est spécifique à MySQL... C'est con, parce que PDO ne sert plus à rien, là... Autant utiliser MySQLi, ça suffit largement...

Bref, j'ai du mal à vraiment comprendre l'intérêt de ta source...

signaler à un administrateur
Commentaire de mytrip le 09/08/2008 21:19:15

l'interet n'est pas l'abstraction au type de db, c'est plutôt abstraction de la syntaxe des requétes.
j'utilise pdo, mais je n'aime pas, par exemple, fetch(PDO::FETCH_ASSOC), j'ai donc étendu la classe pdo pour avoir fetchAssoc().
Le choix de pdo,c'est pour les requetes préparée tout simplement :)
et le jour ou j'ai vraiment besoin de changer de bdd, je peut toujours réecrire ma fonction limit().. mais j'avoue c'était pas mon soucis :)  

je n'aimais pas non plus avoir le nom de mes table en dur dans les requêtes a l'intérieur, et les truc genre:
select pwet_table.row1, pwet_table.row2 ...

je me suis dit que ça serais bien d'avoir un identifiant pour la table et que le nom réelle de la table soit précisé indépendamment.
donc je déclare un table, et cette table je peut y faire des select, insert, update sans me soucier de son nom, et la requêtes s'écris proprement toute seul.

l'idée de départ c'est un peut ça:
// on déclare la table
$this->Table = new Sql('module.news');

// on créer un objet pour une requête select
$select = $this->Table->select('id,user,sujet,texte,categorie');
// on ajoute une clause where ( on peut encore en ajouter )
$select->where('id',':where','=');
// une clause limit
$select->limit($begin,$end);

qui génère ça:
SELECT test_news.id,test_news.user,test_news.sujet,test_news.texte,test_news.categorie FROM test_news WHERE ( test_news.id=:where ) LIMIT 0,10

le nom de la table peut changer, il suffit de modifier le fichier de config, la requete est propre et le code claire.

mais cette source est loin d'être parfaite, je le reconnais, elle ne fait pas tout ;)


signaler à un administrateur
Commentaire de metis15 le 10/08/2008 15:16:28

Yo !! Génial ! ...et pour ceux qui essayent de comprendre un peu PHP/MySQL, peut-on avoir une idée de ce à quoi celà peut servir car là, c'est du chinois.
Une petite application concrète peut-être..? (;o))))

signaler à un administrateur
Commentaire de mytrip le 10/08/2008 15:34:52

ça sert a simplifier l'utilisation des tables d'une bdd
- en faisant abstraction de son nom réelle dans le code
- ça génère des requete proprement
- couplé au requête préparé de pdo aucun risque d'injection sql
- garder un code claire (ça c'est subjectif)
- toute les configuration des tables sont stockées dans un dossier, il est facile de créer un système d'installation pour un petit cms ...

je pense pas que se soit vraiment utile à quelqun qui souhaite débuter, c'est un concept ...
il y'a des chose plus poussée comme propel http://propel.phpdb.org/trac/

mais c'était bien trop lourd pour moi :)

signaler à un administrateur
Commentaire de malalam le 11/08/2008 21:56:17 administrateur CS

Hello,

je passe pas svt ces temps-ci, mais bon, rapide ce soir : ouais, mais non...tu fais une grossière erreur : tu obliges l'utilisateur a avoir le même nommage que toi. Et je ne trouve pas ton nommage très bon, qui plus est.
Et la même structure en plus...non, ton  code est trop ciblé...et ciblé sur toi uniquement, et encore, juste sur UN exemple de table que tu as dû monter un jour.
Si tu veux faire de la surcouche, pense abstraction, là, tu fais du concret inutilisable pour 99% des gens. Cette classe ne servira jamais qu'à toi.

signaler à un administrateur
Commentaire de mytrip le 11/08/2008 23:10:36

je ne comprend pas bien ?

l'exemple afficher est une class qui utilise cette class !
et ce n'est pas la class elle même qui est affiché :)

il y'a afficher ici:
- un cas avec une class effectivement spécialisé pour un module de news,
- et l'autre qui montre la possibilité de faire des requêtes directement.

ma class je l'utilise dans mon petit framework a ma sauce a moi :)
je m'attendais a plein d'autre remarque, je pense que tu as mal regardé ;)

signaler à un administrateur
Commentaire de malalam le 12/08/2008 20:41:33 administrateur CS

Mea culpa, j'ai très mal lu :-)
Donc oublie ces commentaires.
Par contre, maintenant que j'ai lu le contenu du zip (en partie), je suis comme Neige, je comprends quand même mal l'intérêt : simplement parce que je trouve ça bcp plus complexe à utiliser que directement utiliser pdo par exemple. Et surtout, ce que je reproche à tous les packages de e genre (donc pas que le tien :-) : les requêtes deviennent illisibles. Je préfère nettement voir directement un truc du genre
$sQuery = <<<sql
SELECT
t1.bla, t2.bli
FROM
  table1 t1
INNER JOIN table2 t2 ON t2.t1_id = t1.t1_id
WHERE
  t1.t1_where = :sWhere
sql;
avec un bindValue() qui va bien, plutôt que passer par des méthodes pour faire chaque condition de ma clause WHERE par exemple, et la table de ma clause FROM etc...
C'est quand même plus lisible comme ça.
Maintenant, tu me diras, on n'est pas obligé de pousser jusque là avec ta classe. Certes.

Pour surrenchérir à ce que dit Neige, en effet, fais attention au côté "sql compliant" : LIMIT n'est PAS une clause standard. Et quand elle existe pour un moteur DB, elle ne s'utilise pas forcément comme celle de mysql.
Gaffe aussi au driver PDO choisi par l'utilisateur, tu risques d'avoir des surprises...et dans ce sens, ça manque d'exceptions ton truc.

Au final, ça n'est qu'une surcouche de trucs basiques. Tant qu'à réécrire PDOn autant proposer des trucs inédits et plus complexes : gestion poussée des jeux de résultats multiples (poussée car PDO le fait déjà), des trucs sur les tables systèmes facilitant la récupération des types d'un champ ? Insertion/Update avec vérification du types des champs touchés, etc etc...
Manque aussi la gestion des transactions (c'est basique, mais là, ça manque...!), des procédures stockées (ça rejoint svt les jeux de résultats multiples), etc...

Sinon y a de l'idée pour le code :-) A quelques exceptions près (les exceptions notamment, donc, gestion d'erreur poussée).

signaler à un administrateur
Commentaire de mytrip le 13/08/2008 00:21:09

tout a fait d'accord pour les exeptions

pour le coté "sql compliant", je pense que je devrais utiliser une class interface et une class implement pour le type de db.
et, par exemple, recoder le comportement de la fonction limit selon le type de db si besoin dans la class implement.

ce qui m'a fait coder ça, c'est que j'ai souvent les mêmes codes avec des tables au nom différent.
déclarer des variable gobale ou des constante avec le nom des table ne me plaisais pas.
"SELECT ".MA_TABLE.".bla, ".MA_TABLE.".bli" ...
ça deviens vite galère

pour les transactions ça doit passer, puisque ce n'est qu'un extension de pdo.
je n'ai pas encore testé mais c'était dans mon intention de les utiliser :)  

cette classe n'est qu'un ensemble de méthode pour contruire des requêtes (avec des lacune certes) et utilise les méthodes pdo pour le reste.
La plus grosse lacune de cette source a mes yeux, c'est de ne pas gérer les jointures (sauf en passant les requêtes directement biensur).
je n'ai pas trouver de solution pour le moment ... et je me demande bien comment je pourrais faire :/
j'en suis encore au stade expérimentale avec cette source, je l'utilise sur un petit projet test. j'aimerais bien la développer un peu plus sans en faire une énorme usine a gaz (c'est déjà pas mal tordu comme ça là).

en tout cas merci d'avoir pris le temps de regarder la source et de l'avoir commenté ;)


signaler à un administrateur
Commentaire de neigedhiver le 13/08/2008 11:25:39

Salut,

Si tu as souvent la même requête à quelques variables près (comme le nom de la table), pourquoi ne pas utiliser une procédure stockée ?

Concernant la clause particulière LIMIT, je m'étais posé la question à un moment. J'en avais parlé avec Malalam, qui m'avait dit qu'on pouvait tout à fait récupérer tous les enregistrements et utiliser un itérateur (un LimitIterator plus exactement) pour n'accéder qu'aux résultats souhaités.
Une alternative à LIMIT existe, utilisant des variables existe (je ne l'ai pas en tête) et doit se retrouver sur le net grâce à notre ami à tous.

Sinon, toujours dans un soucis de compatibilité de code, il me semble (mais je dis peut-être une bêtise, j'ai commencé seulement hier à me pencher dessus pour mes besoins personnels) que le DSN n'est pas formé de la même manière suivant les SGBDR... Par exemple, et d'après la doc de PHP, un DSN MySQL ressemble à ça :
mysql:host=localhost;port=3306;dbname=mydatabase
on passe alors user et password en argument du constructeur.
Pour PostgreSQL, le DSN ressemble à ça :
pgsql:host=localhost port=5432 dbname=mydatabase user=myself password=topsecret

Rien que pour séparer les "arguments" du DSN, MySQL utilise des points-virgules et pgSQL utilise des espaces.
Et je ne prends que ces deux exemples là... On peut aussi se connecter à MySQL via un socket Unix. On peut se connecter à une base de données Access (beurk, oui, je sais) en utilisant un nom catalogué, ou un DSN plus "classique".
Je manque de pratique de ce côté là pour pouvoir en parler plus en détails.

Je continue de penser que ta classe apporte une surcouche pas vraiment nécessaire, si ce n'est qu'elle peut éventuellement gérer des incompatibilités de code d'un SGBDR à l'autre, et permettre aux requêtes de fonctionner dans tous les cas. Mais ça représente un gros gros boulot... Et je trouve dommage d'avoir à développer une classe spécifique pour gérer chaque SGBDR, alors que PDO est supposé servir à ça... Il y a peut-être encore des progères à faire du côté de PDO...

Cela dit, tu sembles accorder à cette classe une véritable importance didactique, et ça, c'est très très bien.

signaler à un administrateur
Commentaire de mytrip le 16/08/2008 18:53:08

salut :)
pour les procédures stockées ça pourrait faire l'affaire, mais j'aime bien faire des petit "datagrid", avec des trie par nom etc ...
donc dans ces là, je génère les requête automatiquement selon le besoin, ça deviens plus difficile de faire ça avec des procédures stockés... peut être qu'il y'a des solutions, mais je ne les connais pas.
cette class me permet d'avoir un bon contrôle sur ce qui est généré.

je préfère recodé une class si je change de db, plutot que de codé une class qui fait tout.
il suffirais de charger la bonne class selon le driver, mais l'interoperabilité c'est pas mon soucis pour le moment :)


signaler à un administrateur
Commentaire de neigedhiver le 17/08/2008 13:27:15

C'est quand même dommage de ne pas s'inquiéter de l'interopérabilité quand on utilise PDO...
Si tu utilises PDO, tu devrais t'en inquiéter tout de suite, sans forcément l'implémenter... Mais l'avoir en tête et en tenir compte dans ce qu'on fait, ça me parait important...

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

PDO : Use ?; [ par codefalse ] Bonjour à tous !Voila j'aimerai effectuer une requête sur mon serveur mysql pour lui indiquer quelle base de donnée utiliser, donc pour ce faire je fa Utilisation de pdo a la place de l'api mysql [ par sws2007 ] Bonjour tout le monde Est ce que l'utilisation pdo ;pour l'accées aux données de ma base mysql;evite l'utilsation des fonctions qui sécurise les donn extraction date [ par papiona ] Bjrje veux extraire la date d'inscription apartir de ma table pour détirminer le jour,mois et l'année de cette date,voila mon codemais ca marche pas$s calcule automatisé [ par papiona ] Salut a tousje vais vous expliquer mon pbléme :je développe un exemple en php qui permet un client d'inscrire et au moment de cette inscription il doi import BDD access-mysql [ par cisfra ] Bonjour, je suis entrain de travailler sur l'export de BDD Access vers Mysql en utilisant DSN-less(connexion sans  DSN), le problème c'est que j'arriv Conseils pour etre bon devoloppeur php/mysql [ par rmx_dj ] Bonjour, je suis développeur web, je fais du php/mysql . jusqu'ici j'ai encore tendance à mélanger mes codes avec mes pages web, dès fois je parvien probleme d'insertion dans une table mysql [ par boythioune ] j'ai ecrit un source pr une insertion dans une table mais le navigateur me dit ke le champ revenir est inconnu dans la list field je pige mm pas le me menu php/mysql [ par sej080 ] bonjour, suite à une recherche sur google et votre site, je n'ai pas trouvé de réponses à mes questions. Cela vient peut etre du fait que je ne sais p Apllication web en ligne [ par aabou ] Bonjour,J'ai instllé easyphp et j'ai crée la base de mon apllication avec mysql "minformatique" avec 4 tables mais en exécutant le script voici le mes Définir un nombre de colonnes pour un tableau affichant des données d'une requête SQL [ par stark_2097 ] Salut,Je suppose que c'est un rpoblème "récurant" mais j'arrive pas à trouver la réponse à mon problème...J'ai une base SQL avec des données, je souha


Nos sponsors

Sondage...

CalendriCode

Janvier 2009
LMMJVSD
   1234
567891011
12131415161718
19202122232425
262728293031 

Consulter la suite du CalendriCode



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel BAÏSE, Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,406 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.