Classe mysql : Requete pendant traitement

Résolu
grunkz Messages postés 6 Date d'inscription mercredi 30 novembre 2005 Statut Membre Dernière intervention 3 juillet 2008 - 3 juil. 2008 à 09:56
grunkz Messages postés 6 Date d'inscription mercredi 30 novembre 2005 Statut Membre Dernière intervention 3 juillet 2008 - 3 juil. 2008 à 13:06
Bonjour,
Je travail depuis pas mal de temps avec une classe mysql que j'ai développé et là je suis face a un problème que je n'avais jamais rencontré.
Si par exemple je fait une première requête , que je traite le résultat de cette requête et que je souhaite refaire une nouvelle  requête pendant le traitement   :
<?
$sql->query(...);
while($data = $sql->fetch())
{
   ....
  if(...)
  {
         $sql->query(...)
   }
}
?>

Et bien la classe est complétement perdu et va mélanger les deux résultats (en fait elle me sort une erreur mais dans l'idée c'est ca).
J'ai contourné le problème en passant par une seconde instance , mais ca ne me convient que très moyennement.

Voici un extrait de ma classe :

/**
 * Connexion. Connexion ? la base de donn'e
 * @access public
 * @return boolean Etat pour la connexion
 */
     public function connect()
     {
         if($this->connect == NULL)
         {
             $this->connect = mysql_connect($this->bdserv,$this->bduser,$this->bdpass) or die (mysql::error('Connection au serveur '.$this->dbserv.' avec '.$this->dbuser.' ?chou'e.'));
             mysql_select_db($this->bdname,$this->connect) or die (mysql::error('Selection de la base '.$this->dbname.' impossible'));
             return true;
         }
         else
         {
             return FALSE;
         }
     }
    
/**
 * Envoi. Envoi de la requete Mysql
 * @access public
 * @param string $sql Requete sql
 * @return boolean Etat pour l'envoi
 */
     public function query($sql)
     {
         if($this->connect == FALSE)
         {
             mysql::connect();
         }
         if($this->resultat = mysql_query($sql,$this->connect)or die(mysql::error($sql)))
        {
             $this->requete = trim($sql);
             $this->count++;
            return TRUE;
        }
        else
        {
            return FALSE;
        }
     }
    
     public function safesql($string)
     {
         return mysql_real_escape_string($string);
     }
    
/**
 * Derni?re ID. Retourne la derniere ID ins?r?e dans la bdd
 * @access public
 * @return int Derni?re id
 */
     public function last_id()
     {
          return @mysql_insert_id($this->connect);
     }
    
/**
 * Nombre affect?e. Renvoie le nombre de lignes affect?es par la requete pr?c?dente
 * @access public
 * @return int Nombre de ligne
 */
     public function affected()
     {
         if(isset($this->resultat))
         {
             if ( preg_match('`^select`i',$this->requete) )
                 return mysql_num_rows($this->resultat);
          if ( preg_match('`^(insert|update|delete)`i',$this->requete) )
              return mysql_affected_rows($this->connect);
      }
     }
    
/**
 * Réponse mysql. Retourne le résultat de la requete
 * @access public
 * @param string $type Type de tableau souhaité en retour (defaut = associatif)
 * @return array Tableau de la réponse mysql
 */
     public function fetch($type='assoc')
     {
        switch($type)
        {
            case 'assoc' :
                return mysql_fetch_assoc($this->resultat);
                break;
               
            case 'array' :
                return mysql_fetch_array($this->resultat,MYSQL_NUM);
                break;
               
            case 'object' :
                return mysql_fetch_object($this->resultat);
                break;
               
            case 'row' : // Retourne 1 ligne de r?sultat
                return mysql_fetch_row($this->resultat);
                break;
               
            default:
                echo'Erreur dans le type de tableau';
                break;
        }
     }

Merci

4 réponses

neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
3 juil. 2008 à 10:55
Salut,

Le problème c'est que ta classe gère le résultat. Et elle n'en gère qu'un...
Tu as plusieurs options.
Soit ta classe permet de gérer plusieurs résultats de requêtes (dans un tableau), accessible via un id ou quelque chose dans le genre.
Soit tu externalises le résultat sous forme d'un objet retourné par la méthode query() de ta classe.
C'est comme ça que font les classes mysqli et PDO : les résultats sont des objets à part entière. Dans l'idéal, si la classe de résultat implémente l'interface Iterator (en PHP5) c'est encore plus confortable et même plus optimisé en terme de performances, d'évolutivité, etc.

<hr size="2" width="100%" />Neige

N'hésitez pas à lire la doc de PHP avant de poser des questions triviales...
3
grunkz Messages postés 6 Date d'inscription mercredi 30 novembre 2005 Statut Membre Dernière intervention 3 juillet 2008
3 juil. 2008 à 11:44
Me revoila :)

Tout d'abord merci de ta réponse. Voici la modification que j'ai fait , qu'en penses tu ? Du point de vue fonctionnel ça semble marcher comme je le souhaite :

1- Création d'une classe mysqlResult qui à une méthode public (la méthode fetch qui était précédement dans mysql)

2- Modification de la méthode query qui devient :

public function query($sql)
     {
         if($this->connect == FALSE)
         {
             mysql::connect();
         }
         if($this->resultat = mysql_query($sql,$this->connect)or die(mysql::error($sql)))
        {
             $this->requete = trim($sql);
             $this->count++;
             if ( preg_match('`^select`i',$sql) )
             {
                  return new mysqlResult($this->resultat)
              }
               else
                   return $this->affected();
           
        }
        else
        {
            return FALSE;
        }
     }

Cela pose t'il un problème si je laisse la methode fetch également dans la classe mysql , histoire de pas avoit a retoucher le code déja écrit et qui utilise cette classe ?

merci
0
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
3 juil. 2008 à 12:00
Re,

Je sais pas si j'aurais fait comme ça, mais l'important est que :
- ça soit fonctionnel
- tu sois à l'aise avec
- ce soit évolutif
- ce ne soit pas pourri

Disons que tu peux très bien faire une classe mysqlResult très très complète, ou faire le strict minimum : sur ce point là, pas de contrainte, si ce n'est tes besoins. Si ta classe répond à TES besoins, alors cherche pas plus.

Cependant, pour ce qui est du preg_match, je pense que tu te compliques la vie.
mysql_query() retourne toujours une valeur. Ca peut être un booléen (cas d'une requête qui ne revoit pas de résultat comme les requêtes de type INSERT, UPDATE, etc) ou une ressource de type 'mysql result' pour les requetes de type SELECT (ou FALSE en cas d'échec de celle-ci).
Je pense donc que tu devrais simplement vérifier le type de mysql::$resultat avec un truc dans ce genre :

if (gettype($this -> resultat === 'mysql result') {
return new mysqlResult($this->resultat)
}
else {
return $this->affected();
}

Juste un détail : personnellement, je mets systématiquement les accolades pour les blocs if/elseif/else dans un souci de lisibilité. C'est qu'une pratique personnelle, juste une recommandation.

Concernant ta dernière question, pour des raisons de compatibilité ascendante, tu peux laisser la méthode fetch dans ta classe mysql. Il te suffit de savoir (le rappeler dans les commentaires par exemple, ou dans la doc si vous travaillez à plusieurs avec cette classe) que cette méthode travaille sur le dernier résultat stocké par la classe.

Enfin, j'attire ton attention sur l'utilisation d'un itérateur pour gérer ta classe de résultat... Si tu es en PHP5, c'est un réel gain à tous points de vue. Si tu veux pus d'infos sur la question, n'hésite pas ;)

<hr size="2" width="100%" />Neige

N'hésitez pas à lire la doc de PHP avant de poser des questions triviales...
0
grunkz Messages postés 6 Date d'inscription mercredi 30 novembre 2005 Statut Membre Dernière intervention 3 juillet 2008
3 juil. 2008 à 13:06
Merci :)

Pour les itérateurs j'ai jeté un œil et de prime abord ça me semble bien compliqué ^_^
Mais je m'attarderais sur la question promis
0
Rejoignez-nous