IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

fetch() sur Requete multitable


Sujet :

PHP & Base de données

  1. #1
    Membre régulier
    Homme Profil pro
    Retraité Ing Electronique
    Inscrit en
    Mars 2004
    Messages
    369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Retraité Ing Electronique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2004
    Messages : 369
    Points : 121
    Points
    121
    Par défaut fetch() sur Requete multitable
    Bonjour,

    Je suis en train de passer un site plateforme de mysql à PDO avec plus de 1000 requêtes à la base de données.

    Ce site utilise pas mal de requêtes multitables dans lesquelles deux tables peuvent posséder des champs avec des noms identiques.
    Ayez aussi à l'idée, que ces requêtes multitables peuvent, dans certain cas, faire appel plusieurs fois à la même table, et donc avec des noms de données forcément identiques.

    Voila comment on s'en sortait avec mysql sur une requête faisant appel à 2 fois la même table :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $requete = "SELECT t1.data, t2.data FROM table t1";
    $requete = $requete . "LEFT JOIN table t2 ON t2.id2=t1.id1 WHERE  ...";
    $resultat = mysql_query($requette)
    $num_rows = mysql_num_rows($resultat)
    Pour accéder aux données on faisait par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for($row=0;$row<$num_rows;$row++) {
    data1 = mysql_result($resultat,$row,'t1.data');
    data2 = mysql_result($resultat,$row,'t2.data');
    }
    Avec PDO, j'ai voulu retranscrire cette requette avec des fetch(). pour accéder aux données, j'avais pensé faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $resultat = $bdd->query($requette)
    while($row=$resultat->fetch()) {
    $data1 = $row['t1.data']
    $data2 = $row['t2.data']
    }
    Mais PDO me refuse l'écriture t1.data et ne reconnait pas les data concernées

    Alors faut il que l'utilisation de PDO nous force à intervenir dans les requettes sql ?

    En faisant par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $requete = "SELECT t1.data as data1, t2.data as data2 from table1 t1";
    $requete = $requete . "LEFT JOIN table2 t2 ON t2.id=t1.id WHERE  t1.id = NB";
    $resultat = $bdd->query($requete)
    while($row=$resultat->fetch()) {
    $data1 = $row['data1']
    $data2 = $row['data2']
    }
    Merci de vos réponses éclairées

    Zakuli

  2. #2
    Membre émérite
    Avatar de badaze
    Homme Profil pro
    Chef de projets info
    Inscrit en
    Septembre 2002
    Messages
    1 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets info
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2002
    Messages : 1 412
    Points : 2 522
    Points
    2 522
    Par défaut
    Je ne m'étais jamais posé la question car je nomme tous les champs aliassés.
    Je ne sais pas si le code ci-dessous peut t'être utile mais cela peut te donner des idées.

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    <?php 
    class toto {
     
     private $array_names;
     private $pdoStatement;
     
     public function __construct(&$pdoStatement) {
      $this->pdoStatement = $pdoStatement;
      $this->array_names  = array(); 
      for ($i=0;$i<$this->pdoStatement->columnCount();$i++) {
       $meta = $this->pdoStatement->getColumnMeta($i);
       $this->array_names[$i] = $meta['table'].'.'.$meta['name'];
      } 
     }
     
     public function fetch() {
      $ret = array();
      $row = $this->pdoStatement->fetch();
      if ($row !== false) {
       for ($i=0;$i<$this->pdoStatement->columnCount();$i++) {
        $meta = $this->pdoStatement->getColumnMeta($i);
        $ret[$this->array_names[$i]] = $row[$i];
       }  
       return $ret;
      } else {
       return $row;
      }
     }
    }
    //=================================================================================
    define('DB_HOST', '127.0.0.1');
    define('DB_NAME', 'tests');
    define('DB_USER', 'root');
    define('DB_PWD' , '');
    $bdd         = new PDO('mysql:host='.DB_HOST.'; dbname='.DB_NAME,DB_USER,DB_PWD, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
    $query       = "SELECT u1.username, u1.password, u2.username, u2.password as toto FROM `utenti` u1 INNER JOIN `utenti` u2 ON u1.username = u2.username ";
    $prepared    = $bdd->prepare($query);
    $prepared->execute();
    $titi        = new toto($prepared);
    while($row=$titi->fetch()) {
     $data1 = $row['u1.username'];
     $data2 = $row['u1.password']; 
     $data3 = $row['u2.username'];
     $data4 = $row['u2.toto'];  
     print "$data1 - $data2 - $data3 - $data4 <br/>";
    }
    Cela ne sert à rien d'optimiser quelque chose qui ne fonctionne pas.

    Mon site : www.emmella.fr

    Je recherche le manuel de l'Olivetti Logos 80B.

  3. #3
    Membre régulier
    Homme Profil pro
    Retraité Ing Electronique
    Inscrit en
    Mars 2004
    Messages
    369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Retraité Ing Electronique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2004
    Messages : 369
    Points : 121
    Points
    121
    Par défaut
    Merci badaze,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $data1 = $row['u1.username'];
    $data3 = $row['u2.username'];
    Et ce code marche chez toi ?
    Il dissocie bien les deux données ?

  4. #4
    Membre éprouvé Avatar de Willy_k
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2011
    Messages
    540
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2011
    Messages : 540
    Points : 1 067
    Points
    1 067
    Par défaut
    Bonjour,
    Tu peux utiliser ça en bas de ta connexion
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $bdd->setAttribute(PDO::ATTR_FETCH_TABLE_NAMES, true);
    http://php.net/manual/fr/pdo.constants.php pour plus d'infos sur les autres constantes
    Sinon pourquoi tu ne veux pas utiliser d'alias ?
    Le bienfait n'est jamais perdu

  5. #5
    Membre émérite
    Avatar de badaze
    Homme Profil pro
    Chef de projets info
    Inscrit en
    Septembre 2002
    Messages
    1 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets info
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2002
    Messages : 1 412
    Points : 2 522
    Points
    2 522
    Par défaut
    @Willy_k. J'avais cherché un truc comme ça mais je ne l'avais pas trouvé.

    @zakuli. Dans mon cas ce sont les mêmes données (cf l'INNER JOIN) mais ce ne sont pas les mêmes champs (cf le SELECT).
    Cela ne sert à rien d'optimiser quelque chose qui ne fonctionne pas.

    Mon site : www.emmella.fr

    Je recherche le manuel de l'Olivetti Logos 80B.

  6. #6
    Membre régulier
    Homme Profil pro
    Retraité Ing Electronique
    Inscrit en
    Mars 2004
    Messages
    369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Retraité Ing Electronique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2004
    Messages : 369
    Points : 121
    Points
    121
    Par défaut
    Merci willy,

    En première approche, tel qu'énoncée dans sa définition (cf ci-dessous), il me semble que PDO::ATTR_FETCH_TABLE_NAMES ne répond pas vraiment à l'accès multiple à une même table !

    Tu me demandes :Sinon pourquoi tu ne veux pas utiliser d'alias ?
    Personnellement, je trouve tout à fait anormal que le choix du driver impose de modifier les requêtes sql.

    Le driver devrait être capable d'utiliser n'importe quel résultat de requête à la condition bien sûr qu'elle soit conforme à la norme SQL.

    Je trouve le langage SQL extrêmement bien fait et PDO n'en n'est pour l'instant pas à la hauteur.

    J'ai choisi de passer de mysql à PDO, parce qu'on me disait que PDO était beaucoup mieux et avait plus d'avenir que mysqli. Je sais que PDO est toujours en construction, et j'espère qu'il va évoluer rapidement vers un meilleur respect de la norme SQL, mais je me demande si je n'aurais pas dû attendre un peu plus de fiabilité.

    En effet, j'ai déjà repéré quelques bugs avec PDO (avec PDO::closeCursor()) + ce problème d'accès multiple à une même table, ça montre bien que PDO a été mis en production un peu tôt !

    Cordialement et merci à tous

    Zakuli

    PS : définition de PDO::ATTR_FETCH_TABLE_NAMES : Ajoute le contenu de la table de noms dans chaque nom de colonne retourné dans le jeu de résultats. La table de nom et les noms de colonnes sont séparés par un point (.). Le support de cet attribut n'est pas disponible pour tous les pilotes ; il peut ne pas être disponible pour votre driver.
    Donc dans le cas d'un accès multiple à la même table dans une requête il n'y aura pas plus de différenciation entre les données de même nom !

  7. #7
    Membre régulier
    Homme Profil pro
    Retraité Ing Electronique
    Inscrit en
    Mars 2004
    Messages
    369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Retraité Ing Electronique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2004
    Messages : 369
    Points : 121
    Points
    121
    Par défaut
    Merci badaze,

    Citation Envoyé par badaze Voir le message
    @zakuli. Dans mon cas ce sont les mêmes données (cf l'INNER JOIN) mais ce ne sont pas les mêmes champs (cf le SELECT).
    Je ne comprends pas très bien ta réponse, car il me semble que tu utilises deux fois la même table "utenti" contenant au moins les deux champs "username" et "password"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $query = "SELECT u1.username, u1.password, u2.username, u2.password as toto FROM `utenti` u1 INNER JOIN `utenti` u2 ON u1.username = u2.username ";
    La requête me semble parfaite comme exemple d'appel multiple à la même table dans une requête SQL (bien que cette requête n'aurait pas grand intérêt dans la mesure où elle fait appel deux fois au à la même ligne de la table).

    Mais si le code ci-dessous est accepté par ton driver, elle montrerait que chez toi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $data1 = $row['u1.username'];
    $data3 = $row['u2.username'];
    PDO fonctionnerait bien dans ce cadre, raison de ma question.

    Cordialement

    Zakuli

  8. #8
    Membre éprouvé Avatar de Willy_k
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2011
    Messages
    540
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2011
    Messages : 540
    Points : 1 067
    Points
    1 067
    Par défaut
    Pour la mise en production trop tôt, je pense que si c'était le cas, elle ne serait pas aussi utilisée enfin c'est votre avis...
    Peut être que j'ai du mal à comprendre ce que vous demandez, mais j'ai essayé ça chez moi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    <?php
     
    $bdd = new PDO('mysql:host=localhost;dbname=test_db;charset=utf8', 'root', 'root');
    $bdd->setAttribute(PDO::ATTR_FETCH_TABLE_NAMES, true);
     
    $query = $bdd->query('SELECT t1.data, t2.data FROM tables t1 JOIN tables t2 ON t1.toto = t2.tata');
    while ($row= $query->fetch()) {
        echo $row['t1.data'], $row['t2.data']; 
    }
    Mon driver est mysql, encore une fois peut être que j'ai mal compris la demande
    Le bienfait n'est jamais perdu

  9. #9
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Points : 44 155
    Points
    44 155
    Par défaut
    j'espère qu'il va évoluer rapidement vers un meilleur respect de la norme SQL
    PDO ne s'occupe pas des normes SQL, c'est une interface d'abstraction entre PHP et un SGDB.
    Et ce n'est pas une extension jeune en développement, ça fait 12 qu'elle est disponible.
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  10. #10
    Membre régulier
    Homme Profil pro
    Retraité Ing Electronique
    Inscrit en
    Mars 2004
    Messages
    369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Retraité Ing Electronique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2004
    Messages : 369
    Points : 121
    Points
    121
    Par défaut
    Merci Willy,

    Oui, mon driver est aussi mysql.

    Oui, c'est bien ce que je cherche à faire marcher comme requête, mais tu ne me dis pas si ça fonctionne correctement chez toi !

    Chez moi, l'écriture echo $row['t1.data'], $row['t2.data']; est refusée et pour que ça marche, je dois écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <?php
    $bdd = new PDO('mysql:host=localhost;dbname=test_db;charset=utf8', 'root', 'root');
    $bdd->setAttribute(PDO::ATTR_FETCH_TABLE_NAMES, true);
     
    $query = $bdd->query('SELECT t1.data as data1, t2.data as data2 FROM tables t1 JOIN tables t2 ON t1.toto = t2.tata');
    while ($row= $query->fetch()) {
        echo $row['data1'], $row['data2']; 
    }

  11. #11
    Membre éprouvé Avatar de Willy_k
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2011
    Messages
    540
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2011
    Messages : 540
    Points : 1 067
    Points
    1 067
    Par défaut
    Chez moi l'écriture $row['t1.data'] n'est pas refusée et affiche bien la valeur de la colonne....
    Le bienfait n'est jamais perdu

  12. #12
    Membre régulier
    Homme Profil pro
    Retraité Ing Electronique
    Inscrit en
    Mars 2004
    Messages
    369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Retraité Ing Electronique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2004
    Messages : 369
    Points : 121
    Points
    121
    Par défaut
    Sabotage,

    Citation Envoyé par sabotage Voir le message
    PDO ne s'occupe pas des normes SQL, c'est une interface d'abstraction entre PHP et un SGDB.
    Et ce n'est pas une extension jeune en développement, ça fait 12 qu'elle est disponible.
    N'empêche que PDO te mets à disposition l'interface (le driver) te permettant de discuter avec ta base de données (ici mysql) et je suis tout à fait d'accord avec toi sur le fait qu'il doit s'occuper de ses affaires et ne pas forcer à modifier une requête SQL pour lui permettre de l'interpréter correctement !
    Alors peut être que mon driver déconne, mais il fait bien partie de PDO, non ?

    Pour ce qui est de son age, je ne le connaissais pas, j'ai juste lu quelque part qu'il était toujours en développement et qu'il avait encore des bugs ! Mais je n'ai pas vérifié la date de l'info, peut être est ce une info obsolète

    Il est toutefois véridique que certaines clôtures du buffer ne fonctionnent pas bien (PDO::closeCursor), car j'ai des erreurs rares mais effectives sur cette instruction que je dois supprimer dans ces cas là ! Ceci dit, peut être que dans certains cas je ne les avais pas placés au bon endroit, à vérifier !

    Cordialement

    Zakuli

  13. #13
    Membre régulier
    Homme Profil pro
    Retraité Ing Electronique
    Inscrit en
    Mars 2004
    Messages
    369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Retraité Ing Electronique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2004
    Messages : 369
    Points : 121
    Points
    121
    Par défaut
    Merci willy

  14. #14
    Membre émérite
    Avatar de badaze
    Homme Profil pro
    Chef de projets info
    Inscrit en
    Septembre 2002
    Messages
    1 412
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets info
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2002
    Messages : 1 412
    Points : 2 522
    Points
    2 522
    Par défaut
    @Zakuli
    L'exemple de ma requête est trivial. Je n'avais que cette table sous la main.
    C'est la class toto qui fait le boulot. Elle compose les noms des champs et fait le fetch. Attention. C'est un truc fait en 20 minutes donc ce n'est pas spécialement très étudié. Mon but étant de montrer une possibilité.

    Comme je l'écrivais dans mon premier message, j'ai pris l'habitude de nommer tous mes champs donc je n'ais pas ce problème quand je passe de mysql à PDO.
    Cela ne sert à rien d'optimiser quelque chose qui ne fonctionne pas.

    Mon site : www.emmella.fr

    Je recherche le manuel de l'Olivetti Logos 80B.

  15. #15
    Membre expert
    Avatar de Dendrite
    Femme Profil pro
    Développeuse informatique
    Inscrit en
    Juin 2008
    Messages
    2 129
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 58
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeuse informatique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Juin 2008
    Messages : 2 129
    Points : 3 627
    Points
    3 627
    Billets dans le blog
    8
    Par défaut
    Je sais que ça n'est pas la méthode que tu souhaites travailler, mais moi, comme Badaze, dans ces cas-là, pour plus de clarté, je règle ça en mysql d'abord, via des vues.
    Après comme ça, tu peux faire un trivial "select * from v_machin1" dans ton PHP...

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    create or replace view v_machin1 as
    SELECT t1.data as t1_data, t2.data as t2_data
    FROM table t1
    LEFT JOIN table t2 ON t2.id2=t1.id1

    L'autre méthode, toujours côté SQL, et de préfixer tes champs dès le départ dans ta table, cela semble tout à fait redondant dans la table de départ, mais cela évite ensuite de se prendre les pieds dans la requête ou dans la vue... donc pas si con.
    PDO, une soupe et au lit !
    Partir de la fin est un bon moyen de retrouver son chemin. Bibi - 2020

Discussions similaires

  1. requete multitable sur mysql
    Par tianet dans le forum Requêtes
    Réponses: 2
    Dernier message: 08/05/2007, 22h54
  2. [ASA] Problème sur requete ASA
    Par shadeoner dans le forum SQL Anywhere
    Réponses: 6
    Dernier message: 06/04/2005, 14h35
  3. [ASA] Problème sur requete
    Par shadeoner dans le forum SQL Anywhere
    Réponses: 9
    Dernier message: 30/03/2005, 15h59
  4. Calcul sur requete
    Par nicoolas dans le forum Access
    Réponses: 3
    Dernier message: 11/01/2005, 16h50
  5. idees sur requete a simplifier ???
    Par DaxTaz dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 05/07/2004, 09h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo